意味の違いは、PlastyGroveによってリンクされた回答でかなりよく説明されています。
ただし、機能面ではそれほど違いはないようです。それを確認するためにいくつかの例を見てみましょう。まず、通常の機能:
scala> def modN(n: Int, x: Int): Boolean = ((x % n) == 0)
scala> modN(5, _ : Int)
res0: Int => Boolean = <function1>
したがって、最初の整数をすでに指定しているため、<function1>
をとる部分的に適用されますInt
。ここまでは順調ですね。カリー化へ:
scala> def modNCurried(n: Int)(x: Int): Boolean = ((x % n) == 0)
この表記法を使用すると、次のことが機能することを素朴に期待できます。
scala> modNCurried(5)
<console>:9: error: missing arguments for method modN;
follow this method with `_' if you want to treat it as a partially applied function
modNCurried(5)
したがって、複数パラメーターリスト表記は、実際にはすぐにカレー関数を作成するようには見えませんが(おそらく、不要なオーバーヘッドを回避するため)、カレーしたいことを明示的に示すのを待ちます(表記には他にもいくつかの利点があります)。
scala> modNCurried(5) _
res24: Int => Boolean = <function1>
これは以前に得たものとまったく同じなので、表記を除いてここでは違いはありません。もう一つの例:
scala> modN _
res35: (Int, Int) => Boolean = <function2>
scala> modNCurried _
res36: Int => (Int => Boolean) = <function1>
これは、「通常の」関数を部分的に適用すると、すべてのパラメーターを受け取る関数になるのに対し、複数のパラメーターリストを持つ関数を部分的に適用すると、パラメーターリストごとに1つずつ、すべて新しい関数を返す一連の関数が作成されることを示しています。
scala> def foo(a:Int, b:Int)(x:Int)(y:Int): Int = a * b + x - y
scala> foo _
res42: (Int, Int) => Int => (Int => Int) = <function2>
scala> res42(5)
<console>:10: error: not enough arguments for method apply: (v1: Int, v2: Int)Int => (Int => Int) in trait Function2.
Unspecified value parameter v2.
ご覧のとおり、の最初のパラメーターリストにfoo
は2つのパラメーターがあるため、カレーチェーンの最初の関数には2つのパラメーターがあります。
要約すると、部分的に適用された関数は、機能の点でカレー関数と実際には異なりません。これは、任意の関数をカレー関数に変換できることを考えると、簡単に確認できます。
scala> (modN _).curried
res45: Int => (Int => Boolean) = <function1
scala> modNCurried _
res46: Int => (Int => Boolean) = <function1>
ポストスクリプトム
注:例がprintln(filter(nums, modN(2))
後にアンダースコアなしで機能する理由はmodN(2)
、Scalaコンパイラーがプログラマーの便宜のためにアンダースコアを単に想定しているためと思われます。
追加: @asflierlが正しく指摘しているように、「通常の」関数を部分的に適用すると、Scalaは型を推測できないようです。
scala> modN(5, _)
<console>:9: error: missing parameter type for expanded function ((x$1) => modN(5, x$1))
その情報は、複数のパラメーターリスト表記を使用して記述された関数で利用できます。
scala> modNCurried(5) _
res3: Int => Boolean = <function1>
この回答は、これがどのように非常に役立つかを示しています。