← the matrixmodel
Capability — model
Lazy evaluation
Nothing is computed until it is needed.
ALGOL 60 had call-by-name: an argument was an expression, re-evaluated each time it was used — laziness wearing a procedural coat. The idea was made coherent by the Haskell committee in 1990, which made laziness the default and added types to keep it honest.
What it buys is the freedom to define infinite structures. A list of primes is just a sieve over all numbers; a stream is a function that yields when asked; a parser can return “the rest of the input” without deciding how much that is. What it costs is space leaks, non-strict arithmetic surprises, and a debugging story that is genuinely harder to tell.
The trade-off
- Laziness turns “when does this run” into a real question, and stacks of thunk chains can eat memory in ways that look like a leak in code that has no allocations.
- Strictness annotations (seq, bangs) are how you pay back the cost — and they are a second language to learn.
Where it came from
ALGOL 60, 1960 — call-by-name and Jensen’s device; Haskell, 1990 — laziness as the whole point.