部分的に適用する必要がある2つのパラメーターの関数があるとすると、次のように定義する必要があります。
def f(a: Int)(b: Int) = { /* some code */ }
そして、私はそれを部分的に適用することができますdef fWithA = f(a) _
私の質問は次のとおりです。関数をカレーするために、Scalaが複数のパラメーターリストを使用してパラメーターを宣言する必要があるのはなぜですか?必要に応じて任意の機能をカレーできることが望ましい。
部分的に適用する必要がある2つのパラメーターの関数があるとすると、次のように定義する必要があります。
def f(a: Int)(b: Int) = { /* some code */ }
そして、私はそれを部分的に適用することができますdef fWithA = f(a) _
私の質問は次のとおりです。関数をカレーするために、Scalaが複数のパラメーターリストを使用してパラメーターを宣言する必要があるのはなぜですか?必要に応じて任意の機能をカレーできることが望ましい。
実際には、必要な方法を部分的に適用できます。メソッドを呼び出して、パラメータを除外するだけです。
scala> def foo(a: Int, b: Int) = a*b
foo: (a: Int, b: Int)Int
scala> val x = foo(1,_: Int)
x: Int => Int = <function1>
scala> def bar(x: Int, y: Int, z: Int) = x*y+z
bar: (x: Int, y: Int, z: Int)Int
scala> bar(2,_:Int,6)
res0: Int => Int = <function1>
唯一の違いは、欠落している引数のタイプをコンパイラーに通知する必要があることです。そうしないと、オーバーロードされたメソッドを判別できなかったためです。
別の方法として、メソッドではなく実際の関数がある場合は、curried
関数を呼び出すことです。
scala> val f = {(x:Int, y:Int) => x*y}
f: (Int, Int) => Int = <function2>
scala> f.curried
res2: Int => (Int => Int) = <function1>
_
また、 :を使用してメソッドから関数を作成することもできます。
scala> bar _
res6: (Int, Int, Int) => Int = <function3>
そしてそれを呼びますcurried
:
scala> (bar _).curried
res5: Int => (Int => (Int => Int)) = <function1>
「実際の」カリー化にScalaで複数のパラメーターリストが必要ないくつかの理由:
オーバーロード。純粋関数型言語とは異なり、Scalaではメソッドをオーバーロードできます。関数を部分的に適用すると、コンパイラーは、どのオーバーロードを意味するのかを区別できない場合があります。この仕様では、オーバーロードの解決を最初のパラメーターリストに制限しています。
エラーメッセージ。「メソッド呼び出しに十分な引数がありません」は、非常に便利な(そして理解しやすい)エラーメッセージです。任意のメソッドでカリー化を許可した場合、エラーメッセージは「必須:ただし、「矢印の多い関数型」タイプです。
パフォーマンス。JVMで実行すると、メソッドの呼び出しが非常に効率的になりますが、関数(インターフェース呼び出しを経由する)は遅くなります。