scala - 为什么这个 Scala 方法的显式调用允许它被隐式解析?

标签 scala scala-2.8 implicit

为什么这段代码编译失败,但是当我取消注释指示的行时编译成功? (我每晚都使用 Scala 2.8)。似乎显式调用 string2Wrapper允许从那时起隐式使用它。

class A {
  import Implicits.string2Wrapper
  def foo() {
     //string2Wrapper("A") ==> "B" // <-- uncomment
  } 
  def bar() {
    "A" ==> "B"
    "B" ==> "C"
    "C" ==> "D"
  }
  object Implicits {
    implicit def string2Wrapper(s: String) = new Wrapper(s)
    class Wrapper(s: String) {
      def ==>(s2: String) {}
    }
  }
}

编辑 :感谢到目前为止的答案,其中包括指向 Martin Odersky 评论的指针,

"An implicit conversion without explicit result type is visible only in the text following its own definition. That way, we avoid the cyclic reference errors."



我仍然有兴趣找出 1)“循环引用错误”的危险是什么?,以及 2)为什么显式调用会产生任何影响?

最佳答案

显式指定 string2Wrapper 的返回类型可以解决问题。

class A {
  import Implicits._

  def bar() {    
    "A" ==> "B"
    "B" ==> "C"
    "C" ==> "D"
  }
  object Implicits {
    implicit def string2Wrapper(s: String): Wrapper = new Wrapper(s)
    class Wrapper(s: String) {
      def ==>(s2: String) {}
    }
  }
}

定义 Implicits之前 bar也有效:
class A {
  object Implicits {
    implicit def string2Wrapper(s: String) = new Wrapper(s)
    class Wrapper(s: String) {
      def ==>(s2: String) {}
    }
  }

  import Implicits._

  def bar() {    
    "A" ==> "B"
    "B" ==> "C"
    "C" ==> "D"
  } 
}

如果您需要在当前范围内依赖下面定义的隐式转换,请确保注释其返回类型。很确定这已经出现在邮件列表中,并且可能是预期的行为而不是错误。但我现在找不到它。我猜是 foo 中的显式调用触发 bar 的返回类型的类型推断,然后在键入 bar 的内容时有效.

更新

What is the danger of the cyclic reference error?



隐式方法体可以调用需要隐式转换的方法。如果这两个都有推断的返回类型,那么你就陷入了僵局。这不适用于您的示例,但编译器不会尝试检测到这一点。

Why does an explicit call make a difference?



前面的显式调用会触发隐式方法的返回类型的类型推断。这是 Implicits.isValid 中的逻辑
sym.isInitialized ||
      sym.sourceFile == null ||
      (sym.sourceFile ne context.unit.source.file) || 
      hasExplicitResultType(sym) ||
      comesBefore(sym, context.owner)

更新 2

这个最近的错误看起来很相关:https://lampsvn.epfl.ch/trac/scala/ticket/3373

关于scala - 为什么这个 Scala 方法的显式调用允许它被隐式解析?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2731185/

相关文章:

scala - 如何获取第一个成功完成的Future?

scala - 使用重复参数的成本

scala - 在Scala中,我如何给Singleton一个构造函数?

json - 在Scala中解析JSON的最直接方法是什么?

scala - Scala 3 中的类型模式匹配和推理错误

scala - 使用附加隐式参数实现特征方法

Scala 模式匹配打印精美

scala - 使用Scala中的列和索引将数组转换为数据框

scala - 任意类型A的函数组合

scala - 给出/使用 Scala 2 隐式和 Scala 3 之间的区别