気軽に楽しくプログラムと遊ぶ

自分が興味があってためになるかもって思う情報を提供しています。

Procクラスをirbで確かめる

手続きオブジェクト(ブロックをオブジェクト化)

> 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"