10

部分的に適用する必要がある2つのパラメーターの関数があるとすると、次のように定義する必要があります。

def f(a: Int)(b: Int) = { /* some code */ }

そして、私はそれを部分的に適用することができますdef fWithA = f(a) _

私の質問は次のとおりです。関数をカレーするために、Scalaが複数のパラメーターリストを使用してパラメーターを宣言する必要があるのはなぜですか?必要に応じて任意の機能をカレーできることが望ましい。

4

2 に答える 2

24

実際には、必要な方法を部分的に適用できます。メソッドを呼び出して、パラメータを除外するだけです。

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>
于 2012-09-30T11:26:56.277 に答える
15

「実際の」カリー化にScalaで複数のパラメーターリストが必要ないくつかの理由:

  • オーバーロード。純粋関数型言語とは異なり、Scalaではメソッドをオーバーロードできます。関数を部分的に適用すると、コンパイラーは、どのオーバーロードを意味するのかを区別できない場合があります。この仕様では、オーバーロードの解決を最初のパラメーターリストに制限しています。

  • エラーメッセージ。「メソッド呼び出しに十分な引数がありません」は、非常に便利な(そして理解しやすい)エラーメッセージです。任意のメソッドでカリー化を許可した場合、エラーメッセージは「必須:ただし、「矢印の多い関数型」タイプです。

  • パフォーマンス。JVMで実行すると、メソッドの呼び出しが非常に効率的になりますが、関数(インターフェース呼び出しを経由する)は遅くなります。

于 2012-09-30T11:56:41.970 に答える