私はちょうど講義2.2高階関数を見ていました( Scalaの関数型プログラミングの原則)。そこでは、sum関数は次のように定義されています。
def sum(f: Int => Int, a: Int, b: Int) { ... }
後で、同じ関数が次のように定義されます。
def sum(f: Int => Int)(a: Int, b: Int) { ... }
それらは同等のように見えますが、何を選択するのかについての説明はありません。
回答:
回答№1は22番目の定義は、2つの引数リストを持つメソッドを宣言します。暗黙的を無視すると、これは通常、有効にするために使用されます カレー 関数適用。基本的な考え方は、関数のいくつかのパラメーターをバインドできるということです。これにより、残りの引数が少ない別の関数、つまりまだバインドされていない関数が生成されます。簡単な教科書の例を次に示します。
def add(xs: List[Int])(y: Int) =
xs.map(_ + y)
// Bind first argument and store resulting function in f
val f = add(List(2,3,5,7,11))_
println(f(0)) // List(2, 3, 5, 7, 11)
println(f(10)) // List(12, 13, 15, 17, 21)
// Bind first argument and store resulting function in g
val g = add(List(0,1,0,1,0,1))_
println(g(1)) // List(1, 2, 1, 2, 1, 2)
println(g(-1)) // List(-1, 0, -1, 0, -1, 0)
// Regular invocation
println(add(List(1,2,3))(4)) // List(5, 6, 7)
オンラインでのカリー化に関する記事がたくさんあります。たとえば、使い方などです。 Scalaでのカリー化、またはあること Scalaでカレーする複数の方法.
なぜ1つを選ぶのかについて:Haskellでは、基本的に常にカレーバージョンよりもカレーバージョンを選択します。後者はパラメータを部分的にバインドできるという利点があり、カレーバージョンを使用するための「構文ペナルティ」やランタイムペナルティがないためです。これはScalaには当てはまらないので(構文に関しては上記のコードスニペットからわかるように)、メソッド/関数の最も可能性の高いユースケースがわかっている場合を除いて、カレーなしのスタイルを好むかもしれません。 カリー化の恩恵を受ける.
回答№2の場合は1
ある種ですが、正確ではありません。最大の違いは、複数のパラメーターリストがあると、すべてのパラメーターを指定しなくても、関数をより簡単に使用できることです。
例として、次のように2つの関数を定義しましょう。
def sum1(f: Int => Int, a: Int, b: Int) = f(a + b)
def sum2(f: Int => Int)(a: Int, b: Int) = f(a + b)
では、関数を定義しましょう g
これは、パラメーターとして、2つを取る別の関数を取ります Int
sおよびを生成します Int
def g(f: (Int, Int) => Int) = f(3, 5)
のバージョン sum
複数のパラメーターリストを使用すると、最初のリストのパラメーターを指定して、この部分的に適用された関数をに渡すことができます。 g
:
g(sum2(_ + 1))
これはとてもシンプルでとてもきれいです。
のように、個別のパラメータリストなし sum1
、ラムダ式を記述して、 a
そして b
パラメータは次のものから取得されます。
g((a: Int, b: Int) => sum1(_ + 1, a, b))