简体   繁体   中英

Scope of Scala's implicit class conversion

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:

  1. In a selection em with e of type T, if the selector does not denote a member of T. In this case, a view v is searched which is applicable to e and whose result contains a member named m. The search proceeds as in the case of implicit parameters, where the implicit scope is the one of T. If such a view is found, the selection em is converted to v(e).m.

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM