Scala和x27的范围;s隐式类转换

Scala和x27的范围;s隐式类转换,scala,implicit-conversion,Scala,Implicit Conversion,Scala似乎在最大可能的表达式上应用隐式类转换,如下例所示: scala> class B { def b = { println("bb"); true } } defined class B scala> class A { def a = { println("aa"); new B } } defined class A scala> (new A).a.b aa bb res16: Boolean = true scala> class XXX(b: =

Scala似乎在最大可能的表达式上应用隐式类转换,如下例所示:

scala> class B { def b = { println("bb"); true } }
defined class B

scala> class A { def a = { println("aa"); new B } }
defined class A

scala> (new A).a.b
aa
bb
res16: Boolean = true

scala> class XXX(b: => Boolean) { def xxx = 42 }
defined class XXX

scala> implicit def toXXX(b: => Boolean) = new XXX(b)
toXXX: (b: => Boolean)XXX

scala> (new A).a.b.xxx
res18: Int = 42

我很高兴这个事实,但我的问题是SLS的哪一部分指定了这种行为?例如,为什么它不首先将
(新的A.b
计算为
true
,然后对该值应用转换?

包含隐式转换的行

(new A).a.b.xxx
由编译器(即在编译时)转换为

如果在启动Scala时使用
-Xprint:typer
选项,我们可以看到这一点

private[this] val res3: Int = $line5.$read.$iw.$iw.toXXX(new $line2.$read.$iw.$iw.A().a.b).xxx;

由于此转换发生在编译时而不是运行时,Scala不可能在应用转换之前将
(新的A.b
计算为
true
。因此,您得到的行为与您刚开始编写的
toXXX((新的A.A.b).xxx
完全相同。

正如Ryan Hendrickson在邮件列表上回答的那样:

您要查找的[定义]在第7.3节中,在应用视图的三种情况列表中:

  • 在选择e.m和类型T的e中,如果选择器不表示成员 在这种情况下,搜索适用于e的视图v,其结果 包含名为m的成员。搜索与隐式搜索一样进行 参数,其中隐式作用域是T的一个。如果找到这样的视图, 选择e.m转换为v(e).m
  • 因此,编译器只能生成语义上与v(e).m等价的东西,正如您所演示的,当涉及到按名称参数时

    val x = e
    v(x).m
    

    在语义上不等同于
    v(e).m

    但是是什么阻止编译器转换成
    valx=(新的A.b;toXXX(x).xxx
    ?是什么保证了观察到的语义?@Daniel很有趣,因为这种行为目前使得scalaz的
    (file:java.io.file).exists.pure[io]
    按假设工作(
    io(file.exists)
    ),否则IO操作实际上将在IO之外执行。更新:目前正在进行折扣,我建议您使用此处提供的信息回答您的问题。这个答案对我来说很有意义。
    val x = e
    v(x).m