Rubyのメモ。
procとlambdaはどちらもProcクラスのインスタンスなのだけど、違いがある。
そもそものProcの使い方と、lambdaとprocとで何が違うのかを調べてみました。
procはブロックのオブジェクト形態であり、ブロックのように振る舞う。lambdaは少し動作が異なり、ブロックというよりメソッドに近い。
らしい。
Procの実行方法
まず実行方法。
Procの実行方法はcall以外にも配列アクセス演算子やcallを呼び出すシンタックスシュガーがある。
#!/usr/bin/env ruby f = Proc.new {|x,y| x*y } # 以下の書き方は全て同じ意味(Ruby1.9以降) p f.call(2,3) # 6 # [] 配列アクセス演算子 p f[2,3] # 6 # .() シンタックスシュガー p f.(2,3) # 6
lambdaリテラル
通常のlambdaの書き方
incre = lambda {|x| x+1 } p incre.call(2)
lambdaリテラル
incre = ->(x){ x+1 } p incre.call(2)
どちらも同じ意味になる
チェック方法
lambdaとprocのチェックをするには、 lambda? を使う。
先ほどのコードに以下を追加
l = ->(x,y){ x*y } p l.call(2,3) # 6 # lambdaかどうかのチェック p f.lambda? # false p l.lambda? # true
returnを使う場合
proc内でreturn文を使うとprocに変換されたブロックを囲うメソッドから戻ろうとする。
lambdaの中のreturn文は、lambda自身から戻る。
def make_proc(msg) Proc.new { p msg; return } end def test_proc p "start test_proc." proc_obj = make_proc("I'm proc.") proc_obj.call #この行は実行されない p "end test_proc." end begin test_proc rescue => e p e # <LocalJumpError: unexpected return> end def make_lambda(msg) lambda { p msg; return } end def test_lambda p "start test_lambda." lambda_obj = make_lambda("I'm lambda.") lambda_obj.call #実行される p "end test_lambda." end test_lambda
Procへの引数渡し
procはyieldと同様のセマンティクスを使う
p = Proc.new {|x,y| print x,y } p.call(1) p.call(1,2) p.call(1,2,3) p.call([1,2])
余分な引数は捨てられ、足りない値はnilになる。
lambdaはメソッドと同じく宣言した数と同じ引数を渡して呼び出す必要がある。
l = lambda {|x,y| print x,y } l.call(1,2) l.call(1) # ArgumentError l.call(1,2,3) # ArgumentError l.call([1,2]) # ArgumentError l.call(*[1,2]) # *による明示的な展開があるためエラーにならない
- 作者: まつもとゆきひろ,David Flanagan,卜部昌平(監訳),長尾高弘
- 出版社/メーカー: オライリージャパン
- 発売日: 2009/01/26
- メディア: 大型本
- 購入: 21人 クリック: 356回
- この商品を含むブログ (129件) を見る