Skip to content

Lazy Evaluation

Rohit edited this page Jan 23, 2017 · 8 revisions

Recap on CBV and CBN

https://github.com/rohitvg/scala-principles-1/wiki/Substition%20Model%20(CBV,%20CBN)%20and%20Tail%20Recursion#brief-explanation

Lazy Evaluation

Laziness means do things as late as possible, and never do them twice.

Streams solve the problem of unnecessary computations by not computing the tail of the stream unless required. But suffers from a serious potential performance problem: If tail is called several times, the corresponding stream will be recomputed each time.

This problem can be avoided by storing the result of the first evaluation of tail and re-using the stored result instead of recomputing tail.

This optimization is sound, since in a purely functional language an expression produces the same result each time it is evaluated. We call this scheme lazy evaluation (as opposed to by-name evaluation where everything is recomputed, and strict evaluation for normal parameters and val definitions.)

Scala uses strict evaluation by default, but allows lazy evaluation of value definitions with the lazy val form:

lazy val x = expr

This causes x to be evaluated lazily. What this means is that x is evaluated only when its referenced for the first time. For all later times that x is referenced, the same value is used. This is unlike:

def y = expr

where y is also evaluated only when its referenced for the first time, but y is also evaluated every later time it is referenced.

Example

def expr = {
    val x = { print(”x”); 1 }
    lazy val y = { print(”y”); 2 }
    def z = { print(”z”); 3 }
    z + y + x + z + y + x // last line
}
expr

what gets printed as a side effect of evaluating expr?

Solution:

  1. x is printed right away, as it is by value: x (even before the last line comes into play) Now we start with the last line i.e. z + y + x + z + y + x
  2. z is printed as it is referenced: z
  3. y is printed as it is now referenced referenced: y
  4. x is already evaluated, so nothing is printed
  5. z is printed again as it is reevaluated on every reference: z
  6. y is already referenced once, so nothing is printed
  7. x is already evaluated, so nothing is printed

Finally: xzyz

Lazy vals and Streams

In the implementation of Stream in Scala, the tail is implemented as a lazy val so that it is evaluated once when it is referenced, and then re-used everytime it is referenced again.

Clone this wiki locally