liveBook · Manning

Lazy-list cons

As explained in Functional Programming in Scala, Second Edition

Lazy-list Cons is the nonempty lazy-list data constructor whose head and tail are represented by thunks.

Lazy-list Cons is the nonempty LazyList constructor. Unlike strict List Cons, it stores the head and tail as explicit thunks: () => A and () => LazyList[A]. The values are evaluated only when demanded, so constructing a Cons does not evaluate its tail. section 5.2

Pattern matching exposes the thunks rather than their values. Reading the head therefore requires h(), while traversing the tail requires t(). The cons helper accepts by-name arguments, memoizes them with lazy val, and wraps them in delayed functions. section 5.2

The constructor’s evaluation behavior shapes common operations:

  • Taking one element avoids forcing the original tail. section 5.6
  • Taking zero elements forces neither head nor tail. section 5.6
  • Recursive tails can remain suspended, supporting stack-safe lazy construction. section 5.6

A delayed infinite sequence

def from(n: Int): LazyList[Int] = cons(n, from(n + 1))

Listing 5.2 A simple definition for LazyList
enum LazyList[+A]:
  case Empty
  case Cons(h: () => A, t: () => LazyList[A])   #1
 
object LazyList:
  def cons[A](
    hd: => A, tl: => LazyList[A]
  ): LazyList[A] =                              #2
    lazy val head = hd                          #3
    lazy val tail = tl
    Cons(() => head, () => tail)
 
  def empty[A]: LazyList[A] = Empty             #4
 
  def apply[A](as: A*): LazyList[A] =           #5
    if as.isEmpty then empty
    else cons(as.head, apply(as.tail*))

Inspect the complete LazyList definition, including Cons, the by-name cons helper, memoized head and tail values, empty, and apply. section 5.2

How Functional Programming in Scala, Second Edition covers it

How deep it goes
Defines thunk representation, explicit forcing, memoization, and demand-sensitive recursion through concrete operations.
Examples
Uses headOption, take, drop, infinite from sequences, and Fibonacci LazyLists as concrete examples.
What you can do after
Build lazy lists and preserve delayed evaluation when implementing constructors and recursive operations.
How it connects
Connects LazyList Cons to strict List Cons, thunks, lazy evaluation, and recursive stream operations.

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.