Хорошо, это становится смешным. Каждый раз, когда я пытаюсь ответить на вопрос о том, как работают циклы for
в Ruby, я ошибаюсь.
Причина этого, конечно, в том, что я не использую циклы for
в Ruby, как и никто другой, поэтому для меня это не имеет значения: -)
В любом случае, чтобы решить этот вопрос раз и навсегда, я сразу перешел к окончательному источнику , предварительному проекту спецификации языка Ruby IPA от 1 декабря 2009 года (предназначенному стать спецификацией языка Ruby ISO). ):
§11.4.1.2.3 for
выражение
Синтаксис
- для выражения & rarr; для для переменной в выражение do-clause end
- для переменных & rarr; слева | несколько слева
Выражение для выражения for не должно быть выражением скачка .
Семантика
A для выражения оценивается следующим образом:
- Оценить выражение . Пусть
O
будет результирующим значением.
Пусть E
будет вызовом первичного метода формы первичное выражение [здесь нет конца строки] .each do | block-формальный-аргумент-список | block-body end , где значение primary-expression - O
, block-формальный-аргумент-список - for-variable , block-body является составным оператором из do-clause .
Оценить E
, но пропустить шаг c §11.2.2.
Значение для выражения является результирующим значением вызова.
Хорошо, так что в основном это означает, что
for for_variable in expression
do_clause
end
переводится на
O = expression
O.each do |for_variable|
do_clause
end
Или, в вашем случае:
for i in 1..5
puts j if i > 1 #undefined local variable or method `j' (NameError)
j = i
end
переводится на
(1..5).each do |i|
puts j if i > 1 #no excpetion here, works just fine ??!!??
j = i
end
Aha! Но мы кое-что забыли! Там это зловещее «пропустить шаг с §11.2.2.» вещь! Итак, что это говорит?
- Вставить пустой набор привязок локальных переменных в «привязки локальных переменных».
Обратите внимание, что Шаг b
- Установить контекст выполнения на
E
b
.
это не пропущено.
Итак, насколько я вижу, цикл for
получает свой собственный контекст выполнения, который начинается как копия текущего контекста выполнения, но не получает свой собственный набор привязки локальных переменных. IOW: он получает свой собственный динамический контекст выполнения, но не свою собственную лексическую область.
Должен признать, я все еще не уверен, что полностью понимаю, но это не становится более точным, чем это.