Выбрать главу

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.