【问题标题】:Inline function ambiguity in ScalaScala中的内联函数歧义
【发布时间】:2018-10-13 17:17:04
【问题描述】:

当将提升为函数的运算符传递给定义的高阶函数之一时,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)

为什么编译器不允许我只传递速记版本_ * _

【问题讨论】:

  • 问题很明确,有解决方案尝试,有错误消息,解决方案几乎是正确的(直到柯里化),甚至格式也很好,带有内联代码和错误消息的引用块。这个问题值得一票否决 O_o?

标签: scala function


【解决方案1】:

表达式_ * _ 不是(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)

【讨论】:

  • 感谢您的回答!多参数函数不能变成柯里化函数吗?
  • @user3681304 有一个方法.curried。示例:val f = (x: Int, y: Int) => x + y; f.curried。但是柯里化函数没有下划线占位符语法。
猜你喜欢
  • 2017-04-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-09
  • 2012-01-29
  • 1970-01-01
相关资源
最近更新 更多