手続きオブジェクト(ブロックをオブジェクト化)
> f = Proc.new { puts 'OK' } => #<Proc:0x007fed38859da0@(irb):1> > f.call OK => nil
手続きオブジェクト(引数を取る)
> f = Proc.new { |str| puts str } => #<Proc:0x007fed38842fb0@(irb):3> # 引数の数を取得 > f.arity => 1 # 手続きオブジェクトを呼び出す > f.call("NG") NG => nil
ブロック付きメソッドへ手続きオブジェクトを渡して処理する
* f = Proc.new {|i| puts i} => #<Proc:0x007fed39159fb8@(irb):19> > 3.times(&f) 0 1 2 => 3
Proc.newとlambdaの違い
手続きオブジェクト内での引数の数
- Proc.newは引数の数が異なってもエラーとならない。足りない引数はnilで補う。
- lambdaは引数の数が異なるとエラー
f = Proc.new {|a, b, c| p a, b,c } f.call(1,9) 1 9 nil => [1, 9, nil] f = lambda {|a, b, c| p a, b, c} f.call(1,9) ArgumentError: wrong number of arguments (2 for 3)
手続きオブジェクト内での中断
Proc.new
手続きオブジェクト内でbreakした場合、エラーとなる。
手続きオブジェクト内でreturnするとmethod_lambda_returnまで抜ける。
def method_proc_next proc = Proc.new { next p "next"} proc.call p "method_proc" end method_proc_next #=> "next" #=> "method_proc" def method_proc_break proc = Proc.new { break p "break"} proc.call p "method_proc" end method_proc_break #=> "break" #=> LocalJumpError: break from proc-closure def method_proc_return proc = Proc.new { return p "return"} proc.call p "method_proc" end method_proc_return #=> "return"
lambda
手続きオブジェクト内でbreakしてもエラーとならない。
手続きオブジェクト内でreturnしてもmethod_lambda_returnは抜けない。
lambdaはメソッドっぽく振る舞う。
def method_lambda_next proc = lambda{ next p "next"} proc.call p "method_lambda" end method_lambda_next #=> "next" #=> "method_lambda" def method_lambda_break proc = lambda{ break p "break"} proc.call p "method_lambda" end method_lambda_break #=> "break" #=> "method_lambda" def method_lambda_return proc = lambda{ return p "return"} proc.call p "method_lambda" end method_lambda_return #=> "return" #=> "method_lambda"