liveBook · Manning

Lazy evaluation

As explained in Functional Programming in JavaScript

An evaluation strategy that delays computing an expression until its value is required.

Lazy evaluation delays computing an expression until another operation needs its value. It avoids unnecessary function calls and can prevent large inputs from being processed when only a subset is required. JavaScript normally evaluates eagerly, computing an expression as soon as it is bound, whether or not the result is used. section 7.2

Generating only what take needs

Suppose range produces many numbers and take reads only the first few. Eager evaluation runs range completely, then discards most of its output. Lazy evaluation waits until take requests values, so range produces only the required elements. The same issue appears with Maybe.of(student).getOrElse(createNewStudent()): JavaScript eagerly calls createNewStudent even when student is present. A conditional branch avoids that needless call. section 7.2 section 7.2

In JavaScript, functional code can approximate lazy behavior in two practical ways:

  • Use an alternation combinator so a fallback function runs only when the first function returns a falsy result, as in findStudent followed by createNewStudent. section 7.2
  • Use a Lodash chain with map, filter, and take; shortcut fusion defers the chain until value is requested and can stop after three results. section 7.2
  • Treat a function chain as a deferred program: an enrollment chain filters students, extracts grades, averages them, and executes at value(). section 1.3
Figure 7.6. The composition of the function range (returns a list of numbers from beginning to end) with take (reads the first n elements). In eager evaluation, the range function executes completely, feeding its result to take. With lazy evaluation, the result of range never executes until the dependent operation, take, is called.

Compare eager range execution, which creates the full list before take runs, with lazy execution, which waits for take and produces only needed values. section 7.2

Lazy evaluation is an optimization, not a universal improvement: functional code can sometimes be slower or use more memory than imperative code. Use it when avoiding unused work matters, and distinguish it from memoization, which caches results after evaluation. section 7.5

How Functional Programming in JavaScript covers it

How deep it goes
Explains eager-versus-lazy execution, conditional deferral, alternation, and Lodash shortcut fusion, but does not develop language-level lazy evaluation internals.
Examples
Uses range with take, Maybe with a fallback, student lookup, Lodash chains, and an enrollment-average pipeline.
What it assumes
Assumes basic JavaScript functions and functional chains while contrasting them with eager evaluation from the ground up.
What you can do after
Apply it via Lodash chains and functional combinators to defer unused work and limit processing to requested results.
How it connects
Connects lazy evaluation with eager evaluation, function chains, shortcut fusion, alternation combinators, Maybe monads, and memoization.

Also explained in

Compare how 13 books explain lazy evaluation →

Related concepts

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