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)
それで、部分的に適用された関数を簡単に計算できるとしたら、カリー化の利点は何ですか?
カリー化は主に、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がより明確です。
カレーの例を逆にすると、より明確になると思います。
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)
コードのどこにでも、またはこれが特に意味のあることです。見栄えの良い表情が簡単に得られるだけです。
(まあ、型推論に関していくつかの利点があります…)