LJE не из-за возврата из метода, а из-за итератора массива, который вызывает блок. Вы не можете вернуться из итератора массива. Посмотрите, как воспроизводится поведение, просто пытаясь вернуться из следующего блока:
[1,2,3] .each {| x | возврат х}
LocalJumpError: неожиданное возвращение
из (irb): 7
из (irb): 7: в "каждом"
из (irb): 7
РЕДАКТИРОВАТЬ: Хорошо, я забираю это обратно, вы можете вернуться из итератора. Мой ЖЖ был потому, что я был в консоли (аааа).
РЕДАКТИРОВАТЬ: Хорошо, я вижу вашу проблему. Основной вопрос заключается в том, почему block[x]
работает, а yield x
- нет (при условии, что & block - лямбда). Казалось бы, yield x
вставляет интерпретируемый код из блока и вызывает его в контексте итератора массива, который сгенерирует LJE (как указано выше), а block[x]
не вставляет код в код и только возвращает его самого блока.
Итак, не ответив на ваш вопрос, я по крайней мере перевел его на следующее:
def call_as_block(&block)
block.call
end
def call_as_yield
yield
end
proc_return = Proc.new { return }
lambda_return = lambda { return }
call_as_block &proc_return # throws LJE
call_as_yield &proc_return # throws LJE
call_as_block &lambda_return # does NOT throw LJE
call_as_yield &lambda_return # throws LJE
Таким образом, разница, по-видимому, заключается не в лямбде и Proc, которые ведут себя, как ожидается, а в том, что между вызовом лямбды через yield
и вызовом лямбды через block.call
. Вызов yield
, по-видимому, заставляет лямбду вести себя так, как будто это Proc, и пытается вернуться из контекста метода.