Ruby проектировался как непротиворечивый и ортогональный язык. Но вместе с тем это сложный язык, в котором есть свои идиомы и странности. Некоторые из них мы обсудим ниже.
• С помощью ключевого слова alias
можно давать глобальным переменным и методам альтернативные имена (синонимы).
• Пронумерованные глобальные переменные $1
, $2
, $3
и т.д. не могут иметь синонимов.
• Мы не рекомендуем использовать «специальные переменные» $=
, $_
, $/
и им подобные. Иногда они позволяют написать более компактный код, но при этом он не становится более понятным. Поэтому в данной книге мы прибегаем к ним очень редко, что и вам рекомендуем.
• Не путайте операторы диапазона ..
и ...
— первый включает верхнюю границу, второй исключает. Так, диапазон 5..10
включает число 10, а диапазон 5...10
— нет.
• С диапазонами связана одна мелкая деталь, которая может вызвать путаницу. Если дан диапазон m..n
, то метод end
вернет конечную его точку n
, равно как и его синоним last
. Но те же методы возвращают значение n
и для диапазона m...n
, хотя n
не включается в него. Чтобы различить эти две ситуации, предоставляется метод end_excluded?
.
• Не путайте диапазоны с массивами. Следующие два присваивания абсолютно различны:
x = 1..5
x = [1, 2, 3, 4, 5]
Однако есть удобный метод to_a
для преобразования диапазона в массив. (Во многих других типах тоже есть такой метод.)
• Часто бывает необходимо присвоить переменной значение лишь в том случае, когда у нее еще нет никакого значения. Поскольку «неприсвоенная» переменная имеет значение nil
, можно решить эту задачу так: x = x || 5
или сокращенно x ||= 5
. Имейте в виду, что значение false
, а равно и nil
, будет при этом перезаписано.
• В большинстве языков для обмена значений двух переменных нужна дополнительная временная переменная. В Ruby наличие механизма множественного присваивания делает ее излишней: выражение x, y = y, x
обменивает значения x
и y
.
• Четко отличайте класс от экземпляра. Например, у переменной класса @@foobar
областью видимости является весь класс, а переменная экземпляра @foobar
заново создается в каждом объекте класса.
• Аналогично метод класса ассоциирован с тем классом, в котором определен; он не принадлежит никакому конкретному объекту и не может вызываться от имени объекта. При вызове метода класса указывается имя класса, а при вызове метода экземпляра - имя объекта.
• В публикациях, посвященных Ruby, часто для обозначения метода экземпляра применяют решеточную нотацию. Например, мы пишем File.chmod
, чтобы обозначить метод chmod
класса File
, и File#chmod
для обозначения метода экземпляра с таким же именем. Эта нотация не является частью синтаксиса Ruby. Мы старались не пользоваться ей в этой книге.
• В Ruby константы не являются истинно неизменными. Их нельзя изменять в теле методов экземпляра, но из других мест это вполне возможно.
• Ключевое слово yield
пришло из языка CLU и некоторым программистам может быть непонятно. Оно используется внутри итератора, чтобы передать управление блоку, с которым итератор был вызван. В данном случае yield
не означает, что нужно получить результат или вернуть значение. Скорее, речь идет о том, чтобы уступить процессор для работы.
• Составные операторы присваивания +=
, -=
и пр. — это не методы (собственно, это даже не операторы). Это всего лишь «синтаксическая глазурь» или сокращенная форма записи более длинной формы. Поэтому x += y
значит в точности то же самое, что x = x + y
. Если оператор +
перегружен, то оператор +=
«автоматически» учитывает новую семантику.
• Из-за того, как определены составные операторы присваивания, их нельзя использовать для инициализации переменных. Если первое обращение к переменной x
выглядит как x += 1
, возникнет ошибка. Это интуитивно понятно для программистов, если только они не привыкли к языку, в котором переменные автоматически инициализируются нулем или пустым значением.
• Такое поведение можно в некотором смысле обойти. Можно определить операторы для объекта nil
, так что в случае, когда начальное значение переменной равно nil
, мы получим желаемый результат. Так, метод nil.+
, приведенный ниже, позволит инициализировать объект типа string
или Fixnum
, для чего достаточно вернуть аргумент other
. Таким образом, nil + other
будет равно other
.