3

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 的哪一部分指定了这种行为?例如,为什么它不首先评估(new A).a.btrue而只是对该值应用转换?

4

2 回答 2

0

包含隐式转换的行

(new A).a.b.xxx

由编译器(即在编译时)转换为

toXXX((new A).a.b).xxx

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

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

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

于 2012-05-23T21:14:21.373 回答
0

正如 Ryan Hendrickson 在邮件列表中的回答:

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

  1. 在类型为 T 的 e 的选择 em 中,如果选择器不表示 T 的成员。在这种情况下,将搜索适用于 e 并且其结果包含名为 m 的成员的视图 v。搜索与隐式参数的情况一样进行,其中隐式范围是 T 之一。如果找到这样的视图,则选择 em 转换为 v(e).m。

所以编译器只能生成在语义上等同于 v(e).m 的东西,正如你所展示的,当涉及到按名称参数时

val x = e
v(x).m

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

于 2012-05-29T16:35:57.713 回答