当将要提升为功能的运算符传递给已定义的高阶函数之一时,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)
为什么编译器不允许我只传递简写版本_ * _
?
答案 0 :(得分:6)
表达式_ * _
不是(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)