ciuncan
ciuncan

Reputation: 1082

Does accessing type of a lazy val cause it to be evaluated?

As the question title states, does accessing type of a lazy val member result in evaluation of that member? Or does it simply use its static type?

Here is an example code in which I have an implicit lazy val, and I would like to use its type in the method that accept an implicit val with that type:

implicit lazy val nonSpaces: Array[(Point, Part)]

...

def randomNonSpaceCoordinate(implicit nonSpaces: this.nonSpaces.type): Point = nonSpaces(Utils.Random.randUpTo(nonSpaces.length))._1

Upvotes: 3

Views: 707

Answers (2)

Randall Schulz
Randall Schulz

Reputation: 26486

No. Type-level computations (apart from their shadow selves "reflection") are a compile-time thing.

You can verify things like this:

scala> lazy val lv1 = { println("Initializing lv1"); "lv1" }
lv1: String = <lazy>

scala> def m1(s: lv1.type): Int = s.length
m1: (s: lv1.type)Int

scala> lv1
Initializing lv1
res5: String = lv1

However, you may want to think more carefully about using .type like this, since it's a so-called path-depedent type and in a case like this it's probably too narrow to be useful:

scala> m1(lv1)
res6: Int = 3

scala> m1("42")
<console>:10: error: type mismatch;
 found   : String("42")
 required: lv1.type
              m1("42")

In your case, you will only be able to call randomNonSpaceCoordinate with nonSpaces, making it a little pointless to pass it as an argument at all.

Upvotes: 5

senia
senia

Reputation: 38045

Let's check it out:

scala> object Test {
     |   lazy val test: String = {println("bang!"); "value"}
     |   val p: this.test.type = null
     |   def testDef(p: this.test.type) = println(p)
     | }
defined module Test

scala> Test.testDef(Test.p)
null

scala> Test.testDef(Test.test)
bang!
value

So as you can see just accessing the type does not require the lazy val to be actually evaluated.

Upvotes: 5

Related Questions