web-dev-qa-db-ja.com

カリー化v.s.の有用性(実際のアプリケーションのように) Scalaの部分適用

Scalaでの部分適用に対するカリー化の利点を理解しようとしています。次のコードを検討してください。

  def sum(f: Int => Int) = (a: Int, b: Int) => f(a) + f(b)

  def sum2(f: Int => Int, a: Int, b: Int): Int = f(a) + f(b)

  def sum3(f: Int => Int)(a: Int, b: Int): Int = f(a) + f(b)

  val ho = sum({identity})
  val partial = sum2({ identity }, _, _)
  val currying = sum3({ identity })

  val a = currying(2, 2)
  val b = partial(2, 2)
  val c = ho(2, 2)

それで、部分的に適用された関数を簡単に計算できるとしたら、カリー化の利点は何ですか?

54

カリー化は主に、2番目のパラメーターセクションが関数または名前によるパラメーターである場合に使用されます。これには2つの利点があります。まず、関数の引数は中括弧で囲まれたコードブロックのようになります。例えば。

using(new File(name)) { f =>
  ...
}

これは、カレーなしの代替案よりも読みやすくなります。

using(new File(name), f => {
  ...
})

第2に、さらに重要なことに、型推論は通常、関数のパラメーター型を把握できるため、呼び出しサイトで指定する必要はありません。たとえば、次のようなリストに対してmax関数を定義するとします。

def max[T](xs: List[T])(compare: (T, T) => Boolean)

私はそれをこのように呼ぶことができます:

max(List(1, -3, 43, 0)) ((x, y) => x < y)

またはさらに短い:

max(List(1, -3, 43, 0)) (_ < _)

maxをカレーなしの関数として定義した場合、これは機能しません。次のように呼び出す必要があります。

max(List(1, -3, 43, 0), (x: Int, y: Int) => x < y)

最後のパラメーターが関数または名前によるパラメーターでない場合、カリー化はお勧めしません。 Scalaの_表記法は、ほとんど同じくらい軽量で、柔軟性があり、IMOがより明確です。

98
Martin Odersky

カレーの例を逆にすると、より明確になると思います。

def sum4(a: Int, b: Int)(f: Int => Int): Int = f(a) + f(b)

val d = sum4(2, 2) { x =>
  x * x
}

これは光学的な効果ですが、式全体を括弧で囲む必要はありません。もちろん、部分適用を使用するか、引数を反転するヘルパーメソッドを作成することで、同じ結果を得ることができます。重要なのは、そもそもカレー法から始めれば、これらすべてを行う必要はないということです。その意味で、カリー化はAPIとシンタックスシュガーのようなものです。使用することは期待されていません

val partial_sum4 = sum4(2, 2)

コードのどこにでも、またはこれが特に意味のあることです。見栄えの良い表情が簡単に得られるだけです。

(まあ、型推論に関していくつかの利点があります…)

6
Debilski