部分関数は、渡す可能性のある型の値のサブセットに対してのみ有効な関数です。例えば:
val root: PartialFunction[Double,Double] = {
case d if (d >= 0) => math.sqrt(d)
}
scala> root.isDefinedAt(-1)
res0: Boolean = false
scala> root(3)
res1: Double = 1.7320508075688772
これは、関数が定義されているかどうかを確認する方法を知っている場合に役立ちます。たとえば、次のように収集します。
scala> List(0.5, -0.2, 4).collect(root) // List of _only roots which are defined_
res2: List[Double] = List(0.7071067811865476, 2.0)
これは、本当に 1 つが必要な場所に 2 つの引数を配置するのに役立ちません。
対照的に、部分的に適用された関数は、その引数の一部が既に入力されている関数です。
def add(i: Int, j: Int) = i + j
val add5 = add(_: Int,5)
これで、必要な引数は 2 つではなく、1 つの引数 (5 を加算するもの) だけになりました。
scala> add5(2)
res3: Int = 7
この例から、その使用方法を確認できます。
しかし、これらの 2 つの引数を指定する必要がある場合でも、これではうまくいきません。map
たとえば、 を使用したい場合、1 つの引数の関数を指定する必要がありますが、2 つの異なるものを追加する必要があります。さて、あなたはすることができます
val addTupled = (add _).tupled
これは、関数を部分的に適用し (実際には、何も入力されていないため、メソッドから関数を作成するだけです)、個別の引数をタプルに結合します。単一の引数が必要な場所でこれを使用できるようになりました (型が正しいと仮定します)。
scala> List((1,2), (4,5), (3,8)).map(addTupled)
res4: List[Int] = List(3, 9, 11)
対照的に、カリー化はまた別のものです。フォームの関数を に(A,B) => C
変換しA => B => C
ます。つまり、複数の引数を持つ関数を指定すると、それぞれが 1 つの引数を取り、1 つ短いチェーンを返す関数のチェーンが生成されます (一度に 1 つの引数を部分的に適用すると考えることができます)。
val addCurried = (add _).curried
scala> List(1,4,3).map(addCurried)
res5: List[Int => Int] = List(<function1>, <function1>, <function1>)
scala> res5.head(2) // is the first function, should add 1
res6: Int = 3
scala> res5.tail.head(5) // Second function should add 4
res7: Int = 9
scala> res5.last(8) // Third function should add 3
res8: Int = 11