leaning diary Rails

【Learning Diary47】Procクラスとlambdaメソッドの挙動の違い

Procクラスふりかえり

 

Procクラスはブロックとして記述された手続きを持ち運ぶことができるクラスです。

 

Proc.newメソッドまたはprocメソッドにブロックを与えると、そのブロックを保持するProcオブジェクトが作成できます。

 

callで呼び出すと実行されます。

 

hello_1 = Proc.new do |name|
  puts "Hello,#{name}."
end

hello_2 = proc do |name| #procメソッドを使う場合は小文字
  puts "Hello,#{name}."
end

>> hello_1.call("World")
Hello,World.
=> nil

>> hello_2.call("Ruby")
Hello,Ruby.
=> nil

 

lambdaは、Procオブジェクトを生成するメソッドです。

 

Proc.newメソッドまたはprocメソッドと比較すると、lambdaメソッドで作成したProcオブジェクトのほうがメソッド呼び出しに近い動作になります。

 

lambdaメソッドとの違い

■引数の数が厳密にチェックされます

 

Proc.newでつくったProcオブジェクトは、call呼び出しを受ける際に、引数とブロック変数の数が違っても問題ありません。

 

?> prc1 = Proc.new do |a,b,c|
?>  p [a,b,c]
>> end
=> #<Proc:0x000000010337e7a0 (irb):13>
>> prc1.call(1,2)
[1, 2, nil]
=> [1, 2, nil]
>> prc1.call(1)
[1, nil, nil]
=> [1, nil, nil]
>> prc1.call(1,2,3,4)
[1, 2, 3]
=> [1, 2, 3]

 

一方、lambdaではエラーになります。

 

?> prc2 = lambda do |a,b,c|
?>   p [a,b,c]
>> end
=> #<Proc:0x0000000103398470 (irb):22 (lambda)>
>> prc2.call(1,2)
(irb):22:in `block in <top (required)>': wrong number of arguments (given 2, expected 3) (ArgumentError)
    from (irb):25:in `<main>'
    from /Users/tokudome/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/irb-1.9.1/exe/irb:9:in `<top (required)>'
    from /Users/tokudome/.rbenv/versions/3.2.2/bin/irb:25:in `load'
    from /Users/tokudome/.rbenv/versions/3.2.2/bin/irb:25:in `<main>'
>> prc2.call(1,2,3)
[1, 2, 3]
=> [1, 2, 3]
>> prc2.call(1,2,3,4)
(irb):22:in `block in <top (required)>': wrong number of arguments (given 4, expected 3) (ArgumentError)
    from (irb):27:in `<main>'
    from /Users/tokudome/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/irb-1.9.1/exe/irb:9:in `<top (required)>'
    from /Users/tokudome/.rbenv/versions/3.2.2/bin/irb:25:in `load'
    from /Users/tokudome/.rbenv/versions/3.2.2/bin/irb:25:in `<main>'

 

■returnを使えます

 

lambdaで書くと以下になります。

 

?> def power_of(n)
?>   lambda do |x|
?>     return x ** n
?>   end
>> end
=> :power_of
>>
>> cube = power_of(3)
>> p cube.call(5)
125
=> 125

 

Proc.newを使う場合はエラーになります。

 

?> def power_of(n)
?>   Proc.new do |x|
?>     return x ** n
?>   end
>> end
=> :power_of
>>
>> cube = power_of(3)
=> #<Proc:0x0000000103dbb038 (irb):14>
>> p cube.call(5)
(irb):15:in `block in power_of': unexpected return (LocalJumpError)
    from (irb):20:in `<main>'
    from /Users/tokudome/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/irb-1.9.1/exe/irb:9:in `<top (required)>'
    from /Users/tokudome/.rbenv/versions/3.2.2/bin/irb:25:in `load'
    from /Users/tokudome/.rbenv/versions/3.2.2/bin/irb:25:in `<main>'
>>

 

 

 

-leaning diary, Rails