予期される数の引数のみをラムダに渡すための Ruby ショートカット
概要
期待される数の引数 (「引数」) のみをラムダに渡す (残りは無視する) 以下のコードのショートカットはありますか?
args = [:p1, :p2, :p3, :p4, :p5, :p6]
expected_args = args[0...the_lambda.arity]
value = the_lambda.call(*expected_args)
全体像としては、ユーザーがラムダを含む Ruby 構成ファイルを作成できる Ruby プログラムを作成しているということです。ユーザーが必要なパラメーターのみを使用してこれらのラムダを記述できるようにしたいと考えています (使用されないパラメーターを含めるなどの「余分な」入力を行う必要はありません)。
上記のコードを使用すると、ユーザーは次のように書くことができます
my_override = ->(a) {....}
または
my_override = ->(a, b, c) { ....}
コンパイラが文句を言うことはありません。 (ここでのアイデアの一部は、新しいユーザーに教えるときに、パラメーターが 1 つまたは 2 つ以上あるという事実に言及する必要さえないということです。これらの追加機能を単に「保存」して、上級ユーザーに公開することもできます。 ) 最終目標は、ラムダの記述をできるだけ単純にすることです。つまり、ラムダの機能に直接寄与しないユーザー記述コードの要素が含まれるのを避けることを意味します。
解決策
定義上、Ruby ラムダはアリティを考慮しますが、Proc オブジェクトは考慮しません。ラムダにスプラット引数のようなことを行うこともできますが (そのような例を以下に示します)、Proc またはラムダのいずれかを使用する場合は、呼び出し元が予期しないことを行うケースを処理するロジックを追加する必要があります。これは、Proc やラムダよりもメソッドで行う方がはるかに簡単です。
一般に、アリティの問題を回避するために行うべき正しいことは、Proc オブジェクトを使用することです。これは、Proc はアリティを気にしないためです。たとえば、これは 1 つの Array オブジェクトを渡しても複数の Integer オブジェクトを渡しても問題なく機能します。
prc = proc { |a, b| pp a, b }
prc.call [1, 2, 3, 4, 5]
#=> [1, 2]
prc.call 1, 2, 3, 4, 5
#=> [1, 2]
それ以外の場合は、呼び出し元とより緊密に連携するか (これは一般的に悪い設計です)、位置引数を破棄するためだけにスプラッティング引数を作成する必要があります。例えば:
# define +prc+ as a lambda and then coerce it
prc = ->(*ary) { pp ary.flatten.take(2) }
prc.call [1, 2, 3, 4, 5]
#=> [1, 2]
prc.call 1, 2, 3, 4, 5
#=> [1, 2]
いずれにせよ、特殊なケースがあります。考慮する:
prc = proc { |a, b| pp a, b }
prc.call [1, 2, 3, 4, 5], [6, 7]
#=> [[1, 2, 3, 4, 5], [6, 7]]
prc = ->(*ary) { pp ary.flatten.take(2) }
prc.call [1, 2, 3, 4, 5], [6, 7]
# => [1, 2]
呼び出し元が何を渡す可能性があるかわからない場合は、アリティ、キーワード オプション、ダックタイピング、クラス検証、または未知の入力を検証するために必要なその他の健全性チェックを処理できるメソッドを作成するだけでもよいでしょう。手間が省けます。 Proc オブジェクトとラムダはクロージャが必要な場合に便利ですが、それらが定義されているバインディングを閉じること以外に、特定のユースケースでこれが引き起こす頭痛の種と比べて何が得られるのかはわかりません。