Важным различием между процедурой и методом или лямбда является то, как они обрабатывают оператор return.Если метод определен внутри другого метода, оператор return во внутреннем методе завершается только из самого внутреннего метода, тогда внешний метод продолжает выполняться.То же самое касается определения лямбды в лямбде, лямбда в методе или метода в лямбда.Однако, когда в методе определен процесс, оператор return будет выходить из процесса, а также из внешнего (включающего) метода.Пример:
def meditate
puts "Adjusting posture…"
p = Proc.new { puts "Ringing bell…"; return }
p.call
puts "Sitting still…" # This is not executed
end
meditate
Output:
Adjusting posture…
Ringing bell…
Обратите внимание, что последняя строка метода не была выполнена, потому что оператор return внутри proc вышел из метода proc и включающего метода.
Если мы определимproc без включающего (внешнего) метода и использующего оператор return, он выдаст LocalJumpError.
p = Proc.new { puts "Ringing bell…"; return }
p.call
Output:
Ringing bell…
LocalJumpError: unexpected return
Это происходит потому, что когда оператор return достигается внутри proc, а не возвращается из контекста, в котором онбыл вызван, он возвращается из области, в которой он (proc) был определен.В следующем примере LocalJumpError происходит, потому что процесс пытается вернуться из среды верхнего уровня, где он был определен.
def meditate p
puts "Adjusting posture…"
p.call
puts "Sitting still…" # This is not executed
end
p = Proc.new { puts "Ringing bell…"; return }
meditate p
Output:
Adjusting posture…
Ringing bell…
LocalJumpError: unexpected return
Обычно не рекомендуется использовать оператор return вProc.Процессы обычно передаются между методами, и если метод, для которого был определен протокол, уже возвращен, он выдаст исключение.В приведенном ниже примере мы можем просто удалить оператор return.Однако есть случаи, когда нам действительно нужно что-то вернуть.В последнем случае, вероятно, лучше использовать лямбду вместо процедуры.Позже мы увидим, что лямбда-выражения обрабатывают операторы возврата другим способом, более похожим на методы.
Ниже приведен еще один сценарий с оператором return:
def zafu_factory
# This method will return the following proc implicitly
Proc.new { puts "Round black zafu"; return }
end
def meditate
puts "Adjusting posture…"
p = zafu_factory
p.call
puts "Sitting still…" # This is not executed
end
meditate
Output:
Adjusting posture…
Round black zafu
LocalJumpError: unexpected return
Что только что произошло?Метод zafu_factory создал и неявно возвратил процесс.Затем метод вызывался процедурой, и когда был достигнут оператор возврата внутри процедуры, он пытался вернуться из контекста, в котором он был определен (метод zafu_factory).Однако zafu_factory уже возвратил proc, и метод может возвращаться только один раз при каждом вызове.Другими словами, было сгенерировано исключение, потому что метод zafu_factory уже вернулся при вызове proc и попытался вернуться во второй раз.
Подробнее в этом сообщении в блоге о Procs и Lambdas: замыкания в Ruby