puts 'Нет соответствия.'
end
делает не то же самое, что фрагмент
case /Hell/
when 'Hello'
puts 'Есть соответствие.'
else
puts 'Нет соответствия.'
end
Если это вас смущает, просто постарайтесь запомнить. А если не смущает, тем лучше!
• Программисты, привыкшие к С, могут быть озадачены отсутствием предложений break
в ветвях case
. Такое использование break
в Ruby необязательно (и недопустимо). Связано это с тем, что «проваливание» редко бывает желательно при многопутевом ветвлении. В конце каждой ветви when
имеется неявный переход на конец предложения case
. В этом отношении Ruby напоминает Pascal.
• Значения в каждой ветви case
могут быть произвольными. На типы никаких ограничений не налагается. Они не обязаны быть константами; допускаются и переменные, и сложные выражения. Кроме того, в ветви может проверяться попадание в диапазон.
• В ветвях case
могут находиться пустые действия (пустые предложения). Значения в разных ветвях не обязательно должны быть уникальными — допускаются перекрытия, например:
case x
when 0
when 1..5
puts 'Вторая ветвь'
when 5..10
puts 'Третья ветвь'
else
puts 'Четвертая ветвь'
end
Если x принимает значение 0, ничего не делается. Для значения 5 печатается строка «Вторая ветвь» — несмотря на то что 5 удовлетворяет и условию в третьей ветви.
• Перекрытие ветвей допускается потому, что они вычисляются в строгом порядке и выполняется закорачивание. Иными словами, если вычисление выражения в какой-то ветви оказалось успешным, то следующие ветви не вычисляются. Поэтому не стоит помещать в ветви case
выражения, в которых вызываются методы с побочными эффектами. (Впрочем, такие вызовы в любом случае сомнительны). Имейте также в виду, что такое поведение может замаскировать ошибки, которые произошли бы во время выполнения, если бы выражение вычислялось. Например:
case x
when 1..10
puts 'Первая ветвь'
when foobar() # Возможен побочный эффект?
puts 'Вторая ветвь'
when 5/0 # Деление на нуль!
puts 'Третья ветвь'
else
puts 'Четвертая ветвь'
end
Если x находится в диапазоне от 1 до 10, то метод foobar()
не вызывается, а выражение 5/0 (которое, естественно, привело бы к ошибке) не вычисляется.
1.5.4. Рубизмы и идиомы
Материал в этом разделе во многом пересекается с изложенным выше. Но не задумывайтесь особо, почему мы решили разбить его именно таким образом. Просто многие вещи трудно точно классифицировать и организовать единственно правильным образом. Мы ставили себе задачу представить информацию в удобном для усвоения виде.
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. Мы старались не пользоваться ей в этой книге.