/ /これら2つの関数定義は同等ですか? --scala

これらの2つの関数定義は同等ですか? - スカラ

私はちょうど講義2.2高階関数を見ていました( Scalaの関数型プログラミングの原則)。そこでは、sum関数は次のように定義されています。

def sum(f: Int => Int, a: Int, b: Int) { ... }

後で、同じ関数が次のように定義されます。

def sum(f: Int => Int)(a: Int, b: Int) { ... }

それらは同等のように見えますが、何を選択するのかについての説明はありません。

回答:

回答№1は2

2番目の定義は、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つを取る別の関数を取ります Intsおよびを生成します 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))