Программирование на языке Ruby
Шрифт:
6.2.5. Преобразование в массив
Когда диапазон преобразуется в массив, интерпретатор последовательно вызывает метод
Ясно, что для диапазонов чисел типа
6.2.6. Обратные диапазоны
Имеет ли смысл говорить об обратном диапазоне? И да, и нет. Следующий диапазон допустим:
Как видите, мы можем определить обе границы и узнать, что правая граница включена. Но этим перечень возможных операций практически исчерпывается.
Означает ли это, что обратные диапазоны всегда бесполезны? Вовсе нет. В некоторых случаях разумно инкапсулировать границы в один объект.
На самом деле массивы и строки часто принимают обратные диапазоны в качестве индексов, поскольку индексация для них начинается с 0, если отсчитывать от левой границы, и с -1 — если от правой. Поэтому допустимы такие выражения:
6.2.7. Оператор переключения
Диапазон в составе условия обрабатывается особым образом. В этом случае
Такой прием, позаимствованный из языка Perl, бывает полезен. Но понять, как он работает, довольно трудно.
Представьте себе исходный текст программы на Ruby, в который встроена документация, ограниченная маркерами
«Волшебство» объясняется принципом работы оператора переключения.
Во-первых, надо осознать, что «диапазон» сохраняет свое состояние, хотя оно и скрыто. Когда становится истинным условие, заданное в качестве левой границы, сам диапазон принимает значение
Такое поведение полезно во многих случаях, в частности для разбора HTML-документов или конфигурационных файлов, разбитых на разделы, выбора
диапазонов элементов из списков и т.д.Но лично мне такой синтаксис не нравится. Недовольны им и многие другие, включая и самого Маца. Возможно, в будущем эта возможность будет исключена из Ruby. Однако я покажу удобный способ реализовать ту же функциональность по-другому.
Что меня не устраивает в операторе переключения? В контексте предыдущего примера рассмотрим строку, начинающуюся с маркера
Однако при попытке сконструировать диапазон от
Далее, напомню, что в Ruby только
Но предположим, что мы сохранили эти значения в переменных, а потом из них сконструировали диапазон. Все перестанет работать, так как проверка всегда дает
А что если сам диапазон поместить в переменную? Тоже не получится — проверка снова дает
Чтобы понять, в чем дело, нужно осознать, что весь диапазон (включая обе границы) вычисляется на каждой итерации цикла, но с учетом внутреннего состояния. Поэтому оператор переключения — вообще не настоящий диапазон. Тот факт, что он выглядит похожим на диапазон, хотя по сути таковым не является, многие считают «злом».
И наконец, задумаемся о границах в операторе переключения. Они вычисляются каждый раз, но результат вычисления нельзя сохранить в переменной и затем просто подставить ее. В некотором смысле граничные точки оказываются похожи на объекты
И несмотря на все вышесказанное, функциональность-то полезная!.. Можно ли написать класс, который инкапсулирует ее, но при этом не будет таким «магическим»? Можно и даже не очень трудно. В листинге 6.1 приведен простой класс