Lazy Evaluation

In the previous session, the tail of Lazy list will be re-calculated each time it is called.

This problem can be avoided if we store the result of the first evaluation of tail and reuse the stored result.

This optimization is sound since the tail expression will produce the same result each time it is evaluated.

This evaluation is called lazy evaluation. By far, we have 3 evaluations.

  • strict evaluation

    It's for normal parameters and val definition (a.k.a. by-value).

  • by-name evaluation

    Everything is recomputed.

  • lazy evaluation

Lazy Evaluation in Scala

lazy val x = expr

For example,

def expr = {
  val x = { println("x"); 1}
  lazy val y = { println("y"); 1}
  def z = { println("z"); 1}
  z + y + x + z + y + x
}

lazy val res = expr
// The console will print. (explain where the print is triggered.)
// x (val x = { println("x"); 1})
// z (def z = { println("z"); 1})
// y (+ y)
// z (+ z)

RealWorld LazyList

In the previous session, the lazy list has only a lazy tail. However, in the real world, the lazy list has a lazy head, tail and empty.

class LazyList[+T](init :=> State[T]) {
  lazy val state: State[T] = init
}

enum State[T]{
  case Empty
  case Cons(hd: T, tl: LazyList[T])
}