【问题标题】:Recursively using implicit methods in Scala在Scala中递归使用隐式方法
【发布时间】:2011-11-30 03:34:46
【问题描述】:

我想为双精度数组定义一些隐式方法,以使我的代码更简洁。理想情况下,它们应该是这样的:

type Vec = Array[Double]

implicit def enrichVec(v: Vec) = new {
  def /(x: Double) = v map (_/x)
  def *(u: Vec) = (v zip u) map {case (x,y) => x*y} sum
  def normalize = v / math.sqrt(v * v)
}

但是,normalize 函数不能像编写的那样工作,因为 Scala 不会递归地应用隐式方法。具体来说,我收到一个错误Note: implicit method enrichVec is not applicable here because it comes after the application point and it lacks an explicit result type。我可以通过明确写出normalize 的代码来避免这种情况,但这会很丑陋。有更好的解决方案吗?

【问题讨论】:

    标签: scala implicit implicit-methods


    【解决方案1】:

    匿名类禁止递归函数定义。您需要将“RichVec”定义为一个类,然后单独定义隐式转换。

    type Vec = Array[Double]
    implicit def enrichVec(v: Vec) = RichVec( v )
    case class RichVec( v: Vec ) {
      def /(x: Double) = v map (_/x)
      def *(u: Vec) = (v zip u) map {case (x,y) => x*y} sum
      def normalize = v / math.sqrt( v * v )
    }
    

    【讨论】:

    • 这无法编译(我正在尝试使用 Scala 2.9.0-1):error: value / is not a member of Vec
    • 具有讽刺意味的是,如果将隐式移到案例类上方,v / math.sqrt( v * v ) 会起作用
    • 您在这里使用case class 而不仅仅是class 有什么特别的原因吗?
    • RichVec( v ) == RichVec( v ) 适用于案例类。然而,它不是一个完整的 RichVec,并且无论如何都必须重新定义 equals,从而使 case 类的使用对此毫无用处。
    • 总结最后一条评论。不,无论如何都不是基于完整的想法。
    【解决方案2】:

    这行得通:

    type Vec = Array[Double]
    abstract class RichVec(v: Vec) {
      def /(x: Double): Vec
      def *(u: Vec): Double
      def normalize: Vec
    }
    implicit def enrichVec(v: Vec): RichVec = new RichVec( v ) {
      def /(x: Double) = v map (_/x)
      def *(u: Vec) = (v zip u) map {case (x,y) => x*y} sum
      def normalize = v / math.sqrt(v * v)
    }
    

    但还有其他方法可以做到这一点。最重要的是您为隐式指定返回类型

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-05-04
      • 1970-01-01
      • 2012-02-01
      • 2020-07-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多