Techioz Blog

Rubyで関数に引数を事前に入力するにはどうすればよいですか?

概要

関数 foo があるとします。

def foo(A, B, C)
 A + B + C
end

そして、最後のパラメータのみを変更して、次のように呼び出します。

foo("foo", "bar", "123")
foo("foo", "bar", "456")
foo("foo", "bar", "789")

変更されない引数を「ベイク」または「事前入力」するにはどうすればよいですか?それで、foo_baked(“123”) が foo(“foo”, “bar”, “123”) と同じになるような新しい呼び出し可能な foo_baked を取得することになるでしょうか?

そして、次のように使用します。

foo_baked = ...?
foo_baked("123")
foo_baked("456")
foo_baked("789")

def を使用して新しい関数を定義するのではなく、実行時にオンザフライで、おそらく配列に対して foo_baked を作成できるようにしたいことに注意してください。

解決策

Ruby には、カリーメソッドによる関数カリーが組み込まれています。

def foo(a, b, c)
  a + b + c
end

foo_baked = method(:foo).curry.call('foo', 'bar')

# this returns "foobar123"
foo_baked.call('123')

# ArgumentError (wrong number of arguments (given 4, expected 3))
foo_baked.call('123', '234')

Method#curry は、カリー化されたプロシージャを作成します。これは引数が事前にロードされた関数で、メソッドの署名を満たすのに十分な引数が渡された場合にのみ実行されます。

foo_baked.lambda に注意してください。 true を返すため、カリー化されたプロシージャは実際にはラムダです。引数の最大数を超えると ArgumentError が発生することになるため、これは重要です。

カリーにアリティ引数を渡すことで、必須引数以外の追加引数を許可できます。

def foo(*args)
  args.join
end

# does not execute since only 2 arguments have been supplied
foo_baked = method(:foo).curry(3).call('foo', 'bar')

# executes on the third argument
# this returns "foobar123"
foo_baked.call('123')

# this returns "foobar123234"
foo_baked.call('123', '234')