Scala seems to apply the implicit class conversion on the largest possible expression, as in the following example:
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
I'm very happy about this fact, but my question is that which part of the SLS specifies this behavior? Why does it not evaluate (new A).ab
to true
first for example, and just apply the conversion on that value?
The line containing the implicit conversion
(new A).a.b.xxx
gets converted by the compiler (ie, at compile-time) into
toXXX((new A).a.b).xxx
We can see this if you use the -Xprint:typer
option when starting Scala.
private[this] val res3: Int = $line5.$read.$iw.$iw.toXXX(new $line2.$read.$iw.$iw.A().a.b).xxx;
Since this conversion happens at compile-time and not run-time, it would be impossible for Scala to evaluate (new A).ab
to true
before applying the conversion. Thus, the behavior you get is exactly the same as if you has just written toXXX((new A).ab).xxx
in the first place.
As answered by Ryan Hendrickson on the mailing list:
[The definition] you're looking for is in Section 7.3, in the list of the three situations in which views are applied:
So the compiler can only generate something that is semantically equivalent to v(e).m, and as you've demonstrated, when by-name parameters are involved
val x = e
v(x).m
is not semantically equivalent to v(e).m
.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.