関数として持ち上げられた演算子を定義された高階関数の1つに渡す場合、Scalaは非常に簡潔な構文を許可します。たとえば(.product()に簡略化できるという事実を無視してください)。
List(1,2,3).fold(1)(_ * _)
上記に私はただ渡すことができます _ \* _
ただし、独自のおもちゃ関数zipWith()を定義したので、関数を渡すときは非常に明示的にする必要があります。
implicit class EnrichedList[A](val self: List[A]) extends AnyVal {
def zipWith[B, C](that: List[B])
(implicit zipper: A => B => C): List[C] = {
def zipWithHelper(zipper: A => B => C)
(as: List[A])
(bs: List[B]): List[C] = {
(as, bs) match {
case (_, Nil) => Nil
case (Nil, _) => Nil
case (a :: restOfA, b :: restOfB) =>
zipper(a)(b) :: zipWithHelper(zipper)(restOfA)(restOfB)
}
}
zipWithHelper(zipper)(self)(that)
}
}
これ:機能しList(1, 3, 4).zipWith(List(3, 4, 5))(_ * _)
ない、と言って
エラー:(60、46)拡張関数のパラメータータイプがありません((x $ 1:、x $ 2)=> x $ 1. $ times(x $ 2))List(1、3、4).zipWith(List(3、4) 、5))(_ * _)
関数が取る引数のタイプを言う必要があります:
List(1, 3, 4).zipWith(List(3, 4, 5))((x: Int) => (y: Int) => x * y)
なぜコンパイラは私が速記バージョンを渡すことを許可しないの_ * _
ですか?
式_ * _
はの省略形ではありません(x: Int) => (y: Int) => x * y
。の省略形です(x: Int, y: Int) => x * y
。のタイプzipper
を(A, B) => C
ではなくに変更するとA => B => C
、機能するはずです。カリー化は重要であり、恒等関数の単なる名前ではありません。
これはここでコンパイルされます:
implicit class EnrichedList[A](val self: List[A]) {
def zipWith[B, C](that: List[B])
(implicit zipper: (A, B) => C): List[C] = {
def zipWithHelper(zipper: (A, B) => C)
(as: List[A])
(bs: List[B]): List[C] = {
(as, bs) match {
case (_, Nil) => Nil
case (Nil, _) => Nil
case (a :: restOfA, b :: restOfB) =>
zipper(a, b) :: zipWithHelper(zipper)(restOfA)(restOfB)
}
}
zipWithHelper(zipper)(self)(that)
}
}
println( List(1, 3, 4).zipWith(List(3, 4, 5))(_ * _) )
とプリント
List(3, 12, 20)
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加