scalaintermediate

Lazy Evaluation and LazyList Streams

Use lazy evaluation with LazyList for infinite sequences, memoization, and deferred computation.

scala
// Lazy val: computed once on first access
lazy val expensive: Int =
  println("Computing expensive value...")
  Thread.sleep(100)
  42

// LazyList (infinite streams)
val naturals: LazyList[Int] = LazyList.from(1)
val evens: LazyList[Int] = naturals.filter(_ % 2 == 0)

// Fibonacci with LazyList
val fibs: LazyList[BigInt] =
  BigInt(0) #:: BigInt(1) #:: fibs.zip(fibs.tail).map(_ + _)

// Primes via Sieve of Eratosthenes
def sieve(s: LazyList[Int]): LazyList[Int] =
  s.head #:: sieve(s.tail.filter(_ % s.head != 0))
val primes: LazyList[Int] = sieve(LazyList.from(2))

// Powers of 2
val powersOf2: LazyList[BigInt] =
  LazyList.iterate(BigInt(1))(_ * 2)

// Collatz sequence
def collatz(n: Long): LazyList[Long] =
  if n == 1 then LazyList(1)
  else if n % 2 == 0 then n #:: collatz(n / 2)
  else n #:: collatz(3 * n + 1)

// Custom unfold
def unfold[A, S](init: S)(f: S => Option[(A, S)]): LazyList[A] =
  f(init) match
    case Some((value, next)) => value #:: unfold(next)(f)
    case None => LazyList.empty

val countdown = unfold(10) { n =>
  if n >= 0 then Some((n, n - 1)) else None
}

@main def run(): Unit =
  // Lazy val demo
  println("Before lazy access")
  println(s"Expensive: $expensive")  // triggers computation
  println(s"Again: $expensive")      // cached

  // Take from infinite streams
  println(s"First 10 naturals: ${naturals.take(10).toList}")
  println(s"First 10 evens: ${evens.take(10).toList}")
  println(s"First 20 fibs: ${fibs.take(20).toList}")
  println(s"First 20 primes: ${primes.take(20).toList}")
  println(s"First 10 powers of 2: ${powersOf2.take(10).toList}")

  // Collatz
  println(s"Collatz(27): ${collatz(27).toList}")
  println(s"Collatz(27) steps: ${collatz(27).length}")

  // Unfold
  println(s"Countdown: ${countdown.toList}")

  // Lazy processing pipeline
  val result = LazyList.from(1)
    .map(n => n * n)
    .filter(_ % 3 == 0)
    .take(10)
    .toList
  println(s"Squares divisible by 3: $result")

Use Cases

  • Infinite sequence generation
  • Lazy data processing pipelines
  • Mathematical sequence computation

Tags

Related Snippets

Similar patterns you can reuse in the same workflow.