0

When in Scala lazy val initialized? In other words does following code have some benefits from declaring variables as lazy?

  lazy val xOption = table.get(x)
  lazy val yOption = table.get(y)
  lazy val xyOption = table.get(x + y)

 (xOption, yOption, xyOption) match { ... }

Does match operator (method) initialize all three variables?

WelcomeTo
  • 19,843
  • 53
  • 170
  • 286

3 Answers3

5

You could remove match here:

(xOption, yOption, xyOption)

This expression creates Tuple3. Without syntax sugar:

Tuple3.apply(xOption, yOption, xyOption)

apply method declaration:

def apply[T1, T2, T3](_1: T1, _2: T2, _3: T3): (T1, T2, T3)

All parameters are call-by-value, so parameters values evaluated before apply method evaluation.

With call-by-name parameters lazy val will not be evaluated.

match calls unapply method, so evaluation depends on unapply method implementstion:

lazy val a = { println("a"); 1 }
lazy val b = { println("b"); 1 }
lazy val c = { println("c"); 1 }

scala> val s = a #:: b #:: c #:: Stream.empty
a
s: scala.collection.immutable.Stream[Int] = Stream(1, ?)

scala> s match {
     |   case x #:: _ => x
     | }
b
res0: Int = 1

As you can see c is not evaluated, a is evaluated on Stream creation and b is evaluated in #::.unapply method.

senia
  • 37,745
  • 4
  • 88
  • 129
1

From the Scala specification:

The lazy modifier applies to value definitions.

A lazy value is initialized the first time it is accessed (which might never happen at all). Attempting to access a lazy value during its initialization might lead to looping behavior. If an exception is thrown during initialization, the value is considered uninitialized, and a later access will retry to evaluate its right hand side.

Simply put, it will initialize the first time you use it. In your case the first time match expression is called. Though table needs to have x by then.

If you see its implementation (as of Scala 2.10, it is changed in the future versions): It uses the famous Double Locking Idiom: private volatile T result;

    public T getValue() {
        if (result != null) {
            return result;
        } else {
            synchronized (this) {
                if (result == null) {
                    result = //initialize
                    return result;
                } else {
                    return result;
                }
            }
        }
    }
Jatin
  • 31,116
  • 15
  • 98
  • 163
-1

Lazy vals are initialized on the first access them, it is computed after access and then becomes a simple val, from api point of view (some notes about implementation, and this SIP for additional info).

So yes if your patMat construct is the first place where you access to your vals it will make a tuple of three elements with vals value.

And match IS NOT A METHOD or operator it is a language level construct.

Community
  • 1
  • 1
4lex1v
  • 21,367
  • 6
  • 52
  • 86