Это потому, что do
синтаксиса while
является просто синтаксическим сахаром и не имеет ничего общего с do
блока?
Более или менее, да. Это не синтаксический сахар, это просто встроенная языковая конструкция, такая как def
или class
, как уже писал @meagar.
Это не имеет ничего общего с do
блока, за исключением того, что ключевые слова дороги и поэтому повторное использование ключевых слов имеет смысл. (Под «дорогим» я подразумеваю, что они ограничивают программиста в его выразительности.)
В цикле while
есть два способа отделить блок от условия:
- ключевое слово
do
и
- разделитель выражений.
В свою очередь, в Ruby есть два разных разделителя выражений:
- точка с запятой
;
и
- перевод строки
Итак, все три из следующих действительны:
while i = a.shift do puts i end # do
while i = a.shift; puts i end # semicolon
while i = a.shift
puts i end # newline
[Очевидно, что последний не был бы написан таким образом, вы бы поставили end
на новой строке, с отступом, чтобы соответствовать while
. Я просто хотел продемонстрировать, какой минимум необходим для разделения частей цикла while
.]
Между прочим: крайне нелогично ставить условие в скобках. В вашем коде также много лишних точек с запятой. И имя переменной i
обычно зарезервировано для индекса, а не для элемента. (Я обычно использую el
для родовых элементов, но я предпочитаю больше семантических имен.)
Также очень идиоматично повторять коллекцию вручную. Ваш код был бы намного лучше написан как
a.each(&method(:puts)).clear
Мало того, что гораздо проще понять, что это делает (распечатать все элементы массива и удалить все элементы из него), но и гораздо проще написать (нет способа ошибочно получить условие завершения или винт до любых заданий). Это также оказывается более эффективным: ваша версия & Theta; (n 2 ), эта версия & Theta; (n).
И на самом деле, это не совсем то, как вы бы это написали, потому что Kernel#puts
в любом случае уже реализует это поведение. Итак, что бы вы действительно написали бы это
puts a
a.clear
или, может быть, это
a.tap(&method(:puts)).clear
[Примечание: этот самый последний не эквивалентен на 100%. Он печатает новую строку для пустого массива, все остальные ничего не печатают.]
Simple. Очистить. Сжатый. Выразительный. Быстро.
Сравните это с:
while (i = a.shift) do; puts i ; end
Мне на самом деле приходилось запускать это несколько раз, чтобы на 100% понять, что он делает.