liveBook · Manning

LazyList

As explained in Functional Programming in Scala, Second Edition

LazyList is a Scala standard-library sequence type whose elements are computed lazily and that can represent finite or infinite sequences.

LazyList is a Scala sequence whose head and tail are evaluated only when demanded. It can describe finite or infinite sequences, separating the description of a computation from running it. section 5.3 section 5.6

LazyList becomes useful when evaluation should be incremental, reusable, or interruptible:

  • A smart cons constructor memoizes by-name head and tail arguments, so each demanded element is computed at most once. section 5.2.1
  • Operations such as exists, take, and foldRight can inspect only the demanded prefix and stop early. section 5.3
  • An infinite LazyList remains usable when operations consume a finite, productive portion; an always-searching operation may not terminate. section 5.4

An infinite sequence with finite demand

val ones: LazyList[Int] = LazyList.cons(1, ones) ones.take(5).toList // List(1, 1, 1, 1, 1) ones.exists(_ % 2 != 0) // true The recursive definition describes infinitely many values, but take and exists force only enough of the sequence to produce their answers. section 5.4 section 5.6

Listing 5.3 Program trace for LazyList
LazyList(1, 2, 3, 4).map(_ + 10).filter(_ % 2 == 0).toList
 
cons(11, LazyList(2, 3, 4).map(_ + 10)).filter (_ % 2 == 0).toList                             #1
 
LazyList(2, 3, 4).map(_ + 10).filter (_ % 2 == 0).toList                             #2
 
cons(12, LazyList(3, 4).map(_ + 10)).filter (_ % 2 == 0).toList                             #3
 
12 :: LazyList(3, 4).map(_ + 10).filter (_ % 2 == 0).toList                             #4
 
12 :: cons(13, LazyList(4).map(_ + 10)).filter(_ % 2 == 0).toList
 
12 :: LazyList(4).map(_ + 10).filter(_ % 2 == 0).toList
 
12 :: cons(14, LazyList().map(_ + 10)).filter(_ % 2 == 0).toList
 
12 :: 14 :: LazyList().map(_ + 10).filter (_ % 2 == 0).toList                             #5
 
12 :: 14 :: List()                                 #6

Trace how map, filter, and toList incrementally force a LazyList, producing only the elements required by the final result. section 5.3

How Functional Programming in Scala, Second Edition covers it

How deep it goes
Explains by-name parameters, thunks, memoizing smart constructors, short-circuiting folds, infinite generation, and productivity.
Examples
Uses memoized cons, an infinite sequence of ones, short-circuiting exists, an evaluation trace, and unfold exercises.
What it assumes
Assumes familiarity with Scala functions and List-style recursion while teaching strictness, nonstrictness, thunks, and memoization.
What you can do after
Build it from scratch using lazy constructors and unfold, then apply incremental operations such as take, exists, and foldRight.
How it connects
Connects laziness with by-name parameters, thunks, memoization, foldRight, Option, List, and corecursion.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Functional Programming in Scala, Second Edition. The section links point to the parts of the book it draws on.