procとlambdaの違い
初めに
今回はRails開発者が採用面接で聞かれる想定Q&A 53問(翻訳)の中から、procとlambdaの違いについての問いがあり、こちらについて掘り下げていく
前提
procとlambdaの共通点
- procもlambdaも、どちらもブロックをオブジェクト化したものであり、Procクラスのインスタンスである
# proc proc1 = Proc.new { p "procインスタンス"} proc1.call #=> "procインスタンス" p "procは#{proc1.class}クラスです" #=> "procはProcクラスです"
# lambda lambda1 = lambda { p "lambdaインスタンス" } lambda1.call #=> "lambdaインスタンス" p "lambdaは#{lambda1.class}クラスです" #=> "lambdaはProcクラスです"
ブロック(block)
do ~ end
あるいは{}
で囲まれたもの- ブロック単体で存在することはできない
- 引数として渡されたブロックは
yield
によって実行される
本題(procとlambdaの違い)
1. 引数の数
procは想定される引数の数が違っていても、エラーが起きないが、lambdaではエラーが起きる
# proc proc1 = Proc.new { |a,b,c| p a,b,c} proc1.call(2,4) #=> 2 4 nil
# lambda lambda1 = lambda { |a,b,c| p a,b,c} lambda1.call(2,4) #=> Traceback (most recent call last): 1: from block.rb:5:in `<main>' block.rb:4:in `block in <main>': wrong number of arguments (given 2, expected 3) (ArgumentError)
procでは受け取っていない値はnilとなり、エラーは発生していないが、lambdaではエラーが発生していることがわかる
2. ジャンプ構文(return, break)の挙動の違い
procの場合は、returnやbreakが呼び出された場合、呼び出されたメソッドを抜ける挙動になる
# proc def test_proc proc1 = Proc.new { return p "returnが呼び出されました"} proc1.call p "処理は終了です" end test_proc #=> "returnが呼び出されました"
# lambda def test_lambda lambda1 = lambda { return p "returnが呼び出されました"} lambda1.call p "処理は終了です" end test_lambda #=> "returnが呼び出されました" #=> "処理は終了です"
procは
"処理は終了です"
の出力がなく、メソッドを抜けていることがわかる