彼らは少し異なった意味を持っていますが、そのユースケースはほとんど同じです実際にはどのようにしてコード内をどのように見ているのでしょうか。その数学的な意味でのScalaの関数をカリー化
をカリー化
は非常に簡単です:
val function = (x: Int, y: Int, z: Int) => 0
// function: (Int, Int, Int) => Int = <function3>
function.curried
// res0: Int => (Int => (Int => Int)) = <function1>
機能&方法
あなたは(そのScalaで事実によって混同しているように見えます=>
)機能は(def
)の方法と同じではありません。メソッドはファーストクラスのオブジェクトではありませんが、ファンクションはありません(つまり、curried
とtupled
のメソッドを持ち、Function1
はさらに優れています)。
しかし、方法は、η拡張として知られている操作によって機能に持ち上げることができます。詳細については、this SO answerを参照してください。 methodName _
と書くことで手動でトリガーすることもできますし、関数の型が予期される場所にメソッドを渡すと、暗黙的に行われます。
def sumAndAdd4(i: Int, j: Int) = i + j + 4
// sumAndAdd4.curried // <- won't compile
val asFunction = sumAndAdd4 _ // trigger eta expansion
// asFunction: (Int, Int) => Int = <function2>
val asFunction2: (Int, Int) => Int = sumAndAdd4
// asFunction2: (Int, Int) => Int = <function2>
val asFunction3 = sumAndAdd4: (Int, Int) => Int
// asFunction3: (Int, Int) => Int = <function2>
asFunction.curried
// res0: Int => (Int => Int) = <function1>
asFunction2.curried
// res1: Int => (Int => Int) = <function1>
asFunction3.curried
// res2: Int => (Int => Int) = <function1>
{sumAndAdd4 _}.tupled // you can do it inline too
// res3: Int => (Int => Int) = <function1>
複数のパラメータリストのイータ展開は
ご想像のように、ETAの拡大は
def singleArgumentList(x: Int, y: Int) = x + y
def twoArgumentLists(x: Int)(y: Int) = x + y
singleArgumentList _ // (Int, Int) => Int
twoArgumentLists _ // Int => (Int => Int) - curried!
val testSubject = List(1, 2, 3)
testSubject.reduce(singleArgumentList) // Int (6)
testSubject.map(twoArgumentLists) // List[Int => Int]
// testSubject.map(singleArgumentList) // does not compile, map needs Int => A
// testSubject.reduce(twoArgumentLists) // does not compile, reduce needs (Int, Int) => Int
独自の関数にすべてのパラメータのリストを持ち上げるしかし、それは数学的な意味でそのカリー化ではありません。
def hmm(i: Int, j: Int)(s: String, t: String) = s"$i, $j; $s - $t"
{hmm _} // (Int, Int) => (String, String) => String
ここでは、2つの引数の関数を取得し、 2つの引数の関数
そして、それだけでそのargumeの一部を指定することは簡単ではありません機能と同様に、あなたが任意の大騒ぎせずバック機能を得る
val function = hmm(5, 6) _ // <- still need that underscore!
:
val alreadyFunction = (i: Int, j: Int) => (k: Int) => i + j + k
val f = alreadyFunction(4, 5) // Int => Int
やり方あなたはそれが好きです - Scalaは多くのことについてかなり非公式です。私は、関数を部分的に適用し、それをどこかに渡す必要があるので、残りのパラメータが与えられるので、私は明示的にη拡張を行う必要はないので、複数のパラメータリストを個人的に好む私はメソッド定義サイトでより賢い構文を楽しむことができます。
コードに間違いがありますか? functionFirst2を定義しましたが、何もしません。 functionFirstとfunctionSecondは同じです。他に何か意味がありましたか? – costa
はい、addCurは文字列を返すので、 'val x = addCur(" apple ")'は実行できません。なぜなら、コンパイルは部分的なアプリケーションを作るために別の関数を返すことを期待しています。これは有効な 'val x = addCur(" apple ")_'です。 addの場合、これは有効な 'val x = add(" apple ")'関数を返すので有効です。そのとおりです?? –
はいいいえ –