В Ruby «блок» - это код, заключенный в do...end
или в фигурные скобки. (Существуют и другие способы - в некотором роде - создавать блоки в Ruby, но это определение будет держать вас довольно долго.) if...end
не считается блоком. Ни один не while...end
. Чтобы еще больше усложнить проблему, do
, который вы добавляете после while
, также не делает его блоком;Руби просто услужливо игнорирует это.
Кэри уже объяснил это в комментариях, но я посмотрю, смогу ли я немного прояснить это для вас. Я немного упросту и уберу ваш код:
a = 3
while a < 10
b = a * 3
a += 1
end
puts b
Это даст 27. Но теперь, если я сделаю это:
a = 3
loop do
b = a * 3
a += 1
break if a == 10
end
puts b
Я получу это:
undefined local variable or method `b' for main:Object (NameError)
что вы и ожидали. Это потому, что while
является утверждением. while...end
может содержать несколько строк кода, но он не считается блоком. (То же самое для if
.) Но на самом деле loop
- это метод, который принимает блок в качестве аргумента, поэтому применяются правила области видимости, которые Кэри описывает в своем комментарии.