Это то, что я новичок в изучении Ruby, или у него действительно больше способов писать (одинаковые) вещи, чем на Java / C#? Кроме того, если он более гибкий, чем Java, существуют ли какие-либо лингвистические особенности Ruby, которые обычно используются нет, чтобы избежать путаницы?
Примерами могут быть параллельное присваивание и, возможно, все разные способы написания строк?
Примечание: Я не прошу сравнения с Java / C# ... просто вопрос по этому языку, пожалуйста ...
Редактировать: Я понимаю, что C#, Java и Ruby строго типизированы и что только Ruby (например, Python и другие) является динамически типизированным (в то время как Java / C# типизируется статически). В некоторых ответах говорится, что языки с динамической типизацией более гибкие. Обязательно ли это правда и как это влияет на синтаксис? Я спрашиваю только о синтаксической гибкости.
(PHP также динамически типизирован, и, насколько я видел, нет кажется более гибким, чем Java / C#. Опять же, я имею в виду синтаксис, а не развертывание или какой-либо другой аспект ...)

Ruby - динамический язык. C# и Java являются статически типизированными языками со строгой типизацией. C# в версии 4.0 добавит динамические функции, но до сих пор у Java и C# была совершенно другая и более строгая парадигма, чем у динамических языков, таких как Ruby и Python.
На самом деле нет. Это не статически типизировано. Динамическая типизация означает, что переменная не привязана к определенному типу во время компиляции. Значит, тип может измениться. Природа динамической типизации и динамической диспетчеризации дает языкам выдающуюся гибкость, которая менее заметна в статических языках.
Чтобы уточнить, «var x = 5;» в C# статически типизирован, даже если вы не сказали «int x = 5;», C# компилятор выведет его во время компиляции, а «x» будет «int» в обоих случаях. В динамических языках дело обстоит иначе.
Да, Ruby строго типизирован, но строго типизирован! = Статически типизирован. В Java переменные имеют типы - в Ruby значения имеют типы.
Рене, точно. Это было то, что я очень старался сказать, ваше заявление было простым и отличным!
Спасибо, Мердад. Я до сих пор не понимаю, как ваш ответ на самом деле отвечает на вопрос. Ruby не имеет статической типизации, в отличие от C# / Java. Все три строго типизированы. Так?
Ruby не имеет типа статически, в то время как C# / Java. Динамическая типизация позволяет отложить множество проверок до времени выполнения и не беспокоить программиста во время компиляции о неразрешенных ссылках на методы или подобных вещах.
Есть разница между «статически типизированным» и «строго типизированным». Python имеет динамическую типизацию, но также и строго типизирован. Такие языки, как PHP, слабо типизированы, что означает, что тип меняется в зависимости от контекста. Например, добавление двух числовых строк может дать число.
Все языки с динамической типизацией (например, Ruby) обычно более гибкие, чем языки со статической типизацией (например, Java). Вам не нужно бороться с системой типов, что вы часто делаете в статически типизированных языках.
Другой динамический язык, очень похожий на Ruby, - это Python. Однако в Дзен Python одно из правил гласит, что «должен быть один и только один способ что-то делать». Это полная противоположность Ruby, которая допускает столько метапрограммирования, что существует практически бесконечное количество способов сделать то же самое.
Тем не менее, это несколько иронично, что до Python 3.0 (он же 3000) строковые значения и значения Unicode были разными типами. Хотя это имеет смысл, люди иногда сталкиваются с проблемами, когда они много конвертируют между ними для выполнения текстовых операций.
Если у вас есть выбор, я бы почти рекомендовал использовать Python в качестве введения в динамические языки. В Ruby нет ничего плохого, но вы можете столкнуться с меньшим количеством ситуаций, когда «правильный» способ сделать что-то не совсем очевиден.
В ответ на динамическую типизацию PHP:
Система типов PHP является гибкой, позволяя автоматически преобразовывать типы в зависимости от того, в каком контексте они используются. Однако на самом деле это не делает настоящие динамические типы. Сам язык в основном статичен и не позволяет добавлять атрибуты к объектам, например, во время выполнения (по крайней мере, в последний раз, когда я проверял).
Python и, вполне возможно, Ruby на самом деле строго типизированы, что означает, что вы можете уверенно проводить сравнение типов и не можете использовать PHP-трюки, такие как добавление числовых строк для получения числа. Истинные динамические языки также часто допускают мета-класс, где вы можете настроить тип экземпляра или класса или добавить атрибуты к любому из них во время выполнения.
Спасибо. Замечательный и отличный ответ. А как насчет сравнения с нединамическими языками, такими как Java и C#? [У меня нет выбора: меня «заставляют» использовать Ruby и Rails.]
Также позвольте мне упомянуть, что, хотя это не по теме, у Ruby есть Rails, а у Python есть миллион различных вариантов, включая DJango. И я думаю, что в наши дни наличие Бога чего-то стоит.
На мой взгляд, наиболее часто используемые функции в Ruby и отсутствующие в Java - это блоки кода / лямбда-выражения / замыкания.
Еще одна замечательная (но, возможно, опасная) функция - это открытые классы - вы можете изменить любой класс, который хотите - добавить новый метод, изменить старый и т.д. Вы даже можете добавить метод к конкретному объекту, а не ко всему классу :).
Слово для описания второго абзаца - метапрограммирование. не критикуя вас, это хорошее объяснение, просто добавляя свои мысли.
Отличный ответ. Не могли бы вы привести крошечный пример блока / лямбда / закрытия? Кроме того, что вы лично НЕ используете в Ruby, потому что это слишком опасно? Спасибо за Ваш ответ.
Очень часто вы хотите предоставить методу данные, которые влияют на его результат. Что, если бы вы могли таким же образом снабдить метод процедурой? Очень хорошая статья под названием "Может ли ваш язык программирования это делать?" особенности блога JoelOnSoftware; joelonsoftware.com/items/2006/08/01.html
Я не знаю Java или C#, но позволяю тому факту, что вы можете переопределить, как + работает с числами, говорит сам за себя.
Что он говорит, когда говорит сам за себя? «Я не существую на Java, используйте меня с осторожностью?»
Или это «как и я, есть целый ряд других гибких функций Ruby, которых нет в Java / C#?»
Я прокомментировал ответ rkj выше относительно лямбды. Этот код демонстрирует запрошенный вами пример;
def abs(n); (n < 0) ? -n : n; end
def square(n); n * n; end
def average(x, y); (x + y) / 2; end
def fixed_point(x, point, process, test)
return point if test.call(x, point)
fixed_point(x, process.call(x, point), process, test)
end
def sqrt(n)
process = lambda {|n,g| average g, (n/g) }
test = lambda {|n,g| abs(square(g) - n) < 0.001}
fixed_point(n, 1.0, process, test)
end
Первое, на что следует обратить внимание, это то, что метод fixed_point реализует общую идею постепенного применения процесса к некоторым данным, пока они не пройдут определенный тест. Функция sqrt определяет процесс нахождения квадратного корня и тест, чтобы определить, когда мы должны быть удовлетворены. Эти «процедуры» затем передаются так же, как и любая другая форма данных, так что fixed_point может творить чудеса.
Вместо временного сохранения процесса и тестирования все это может быть анонимным. Мы могли бы переписать sqrt как;
def sqrt(n)
fixed_point( n, 1.0,
lambda {|n,g| average g, (n/g)},
lambda {|n,g| abs(square(g) - n) < 0.001} )
end
Без этой возможности мне пришлось бы определять и процесс, и тест как отдельные функции и создавать специальную функцию sqrt_fixed_point для их вызова. Насколько мне известно, Java может делать что-то подобное с использованием функторов, но я не знаю достаточно, чтобы комментировать. В блогах я видел консенсус в том, что Java делает это настолько ужасно сложным, что вы получите кровотечение из носа, просто попробовав это.
Конечно, другой вариант, который предлагает Ruby, - это метапрограммирование. Я мог бы переписать sqrt так, чтобы он перезаписывал (на лету) fixed_point, используя правильный процесс и тест, но это, вероятно, злоупотребление функцией :-)
пс. Размещенная ссылка на JoelOnSoftware заслуживает повторения; http://www.joelonsoftware.com/items/2006/08/01.html
Спасибо за это. Мне придется перечитать это после сна. Я отмечу одну вещь: ламба и блоки симпатичны, но неанонимные функции выполняют ОГРОМНУЮ функцию: они дают имена блокам кода ... реальные имена с реальными именами ЛОКАЛЬНЫХ переменных. Это упрощает понимание кода, и это хорошо (при условии, что он по сути эквивалентен) ... в любом случае, я буду комментировать больше, когда проработаю этот материал с фиксированной точкой.
Замечательный материал, спасибо за это. Я действительно думаю, что часть этого синтаксического сжатия (например, ваш последний метод sqrt) приводит к тому, что код использует меньше символов, но менее читабелен и НЕ более эффективен. Лямбды определены, но не присваиваются переменным. Я УГАДАЮ, что для Ruby это то же самое (скажем, для эффективности), но код не так удобочитаем. Если вы не играете в гольф-код, я предпочитаю определять переменные всякий раз, когда это имеет смысл. В любом случае спасибо и +1.
Но Ruby тоже строго типизирован, верно? В любом случае, как это изменит ваши варианты? Это просто означает, что вам не нужно определять типы переменных ... нет?