Webエンジニアへの転職を目指して、現在Ruby、Railsを学習中。

【Ruby】Procオブジェクトの引数の扱いの違いについて

はじめに

Rubyでブロックをオブジェクト化したいとき、Procクラスが用意されています。Procオブジェクトの生成方法は複数ありますが、今回はそれらの引数の扱いの違いについて、学んだことをまとめたいと思います。(Ruby2.5.1)

Procオブジェクトの生成方法

Procオブジェクトの生成方法は複数ありますが、その中でも今回は以下の4つを例に挙げたいと思います。

#①Procクラスのnewメソッドを使う
Proc.new {...}

#②Kernelモジュールのprocメソッドを使う
proc {...}

#③ラムダリテラルを使う
-> {...}

#④Kernelモジュールのlambdaメソッド を使う
lambda {...}  


ここでは①と②をProc.new③と④をラムダと呼ぶことにします。

ラムダのほうが引数の扱いに厳密である

Proc.newとラムダでは、ラムダの方が引数のチェックが厳しく、引数に過不足があるとエラーが発生します。

実際のコード

a,bの2つの引数を取り、それらを表示するProcオブジェクトを作ります。

・ Proc.new

引数の過不足による引数エラーは発生しません。

proc = Proc.new { |a, b| p "#{a}, #{b}" }
proc.call(1)        #=> "1, " 
proc.call(1, 2, 3)  #=> "1, 2"               
proc = proc { |a, b| p "#{a}, #{b}" }
proc.call(1)        #=> "1, "
proc.call(1, 2, 3)  #=> "1, 2"      

・ ラムダ

引数に過不足があると引数エラーが発生します。

lambda = -> (a, b) { p "#{a}, #{b}" }
lambda.call(1) 
#=> ArgumentError: wrong number of arguments (given 1, expected 2) 
lambda.call(1, 2, 3) 
#=> ArgumentError: wrong number of arguments (given 3, expected 2)            
lambda = lambda { |a, b| p "#{a}, #{b}" }
lambda.call(1) 
#=> ArgumentError: wrong number of arguments (given 1, expected 2)  
lambda.call(1, 2, 3) 
#=> ArgumentError: wrong number of arguments (given 3, expected 2)          


引数の取扱の厳密さを確かめる

Procオブジェクトの引数の取扱の厳密さを確認したいとき、.lambda?メソッドが使えます。 引数の扱いが厳密であれば、.lambda?メソッドはtrueを返します。

proc = Proc.new { |a, b| p "#{a}, #{b}" }
proc.class    #=> Proc
proc.lambda?  #=> false
lambda = -> (a, b) { p "#{a}, #{b}" }
lambda.class    #=> Proc
lambda.lambda?  #=> true

Ruby リファレンスマニュアル https://docs.ruby-lang.org/ja/latest/method/Proc/i/lambda=3f.html

まとめ

Proc.newとラムダでは、ラムダの方が引数の扱いが厳密で、.lambda?メソッドで引数の取扱の厳密さを確認することができました。

参考文献