2010-10-18 120 views
11

任何人都可以使用Scala隐式转换机制解释我的情况。有一个代码:关于Scala隐式转换的问题非歧义性规则

object Main { 
    implicit val x:Int => String = v => "val" 
    implicit def y(v:Int) = "def" 

    def p(s:String) = print(s) 

    def main(args: Array[String]): Unit = { 
     p(1) 
    } 
} 

此代码打印“val”。但是当我评论第二行时:

//implicit val x:Int => String = v => "val" 

代码打印“def”。

因此,在这种情况下,隐式转换(x和y)都是可能的。有一个非歧义规则 - 只有在没有其他可能的插入转换时才会插入隐式转换。根据这个规则,这个代码不应该被编译。但代码已成功编译并执行。我不明白?

谢谢。

回答

9

原因在Scala语言规范第6.26.2节中说明。

在将该方法视为函数之前,需要通过执行eta-expansion将其转换为一个函数。因此需要应用更多的隐式转换,因此选择val

UPDATE:删除有缺陷的示例。

不带参数的方法的评估总是隐含地执行。

+0

你好,莫里茨。谢谢你的回答。因此,当Scala编译器看到其类型与预期类型不匹配的表达式时,它会查找类型T => F的隐式转换,如果未找到此类转换,编译器会尝试在可用方法表达式上执行Eta扩展或空应用程序Scala语言规范中的“否则”一词表示此操作将在之后执行)。我是否理解这一切? – 2010-10-18 21:54:02

+0

但在你的例子中,如果我评论//隐式val =“世界”,代码将不会被编译。 Scala编译器似乎没有考虑空应用程序。 – 2010-10-18 22:29:47

+0

当应用程序搜索隐式转换,但仅用于填充其他隐式参数时,空应用程序实际上并未使用AFAICT。如果你编写'implicit def i2s():Int => String = _.toString',这不会被认为是从String到Int的转换的候选对象。除此之外,它是正确的 - 如果不能直接评估值,则6.26.2列表中的转换从上到下进行尝试。 – Moritz 2010-10-18 22:45:34