Skip to content

Lazy Evaluation

Prime #
955
Origin domain
Software Computing
Subdomain
programming languages → Software Computing
Aliases
Call by Need, Deferred Evaluation

Core Idea

Lazy evaluation is the discipline of doing work only when its result is actually demanded: hold a cheap deferred specification in place of the result, bind execution to downstream demand, and tolerate the work being never done at all.

How would you explain it like I'm…

Cook Only When Asked

Imagine you only cook a meal the moment someone is actually hungry and asks for it, instead of cooking every meal in the morning just in case. If nobody ever asks, you never cook it, and you save all that work. You also write down what you cooked so you don't have to make it twice.

Only When Needed

Lazy Evaluation is the rule of doing a piece of work only when its result is really needed, not the moment you could do it. Instead of computing something right away, you make a cheap little promise that says, 'I can give you this answer if you ask,' and you leave the promise alone — maybe forever — until something downstream actually wants the answer. Once you do the work, you save the result so you never repeat it. And if the answer is never asked for, the work simply never happens, which can save a lot of effort. The opposite habit is doing everything up front whether or not it's needed.

Work on Demand

Lazy Evaluation is the discipline of doing work only when its result is actually demanded. Instead of computing a value the moment its inputs are ready, you produce a cheap promise that can deliver the value if asked, and let it sit untouched, possibly forever, until something downstream consumes it. Four commitments define it: separate the moment work is specified from the moment it's performed; tie the timing to demand from downstream rather than to input availability; record the result once produced so it isn't repeated; and tolerate that the work might never be needed and so never done. Its opposite, eager evaluation, computes everything up front whether or not it's needed, and seeing them as a pair is what makes the choice visible. Lazy pays a small bookkeeping cost to hold the promise, in exchange for maybe skipping much larger unneeded work and gaining the option to act later with better information; neither always wins.

 

Lazy Evaluation is the discipline of doing work only when its result is actually demanded. Rather than computing every quantity the moment its inputs become available, it produces a deferred specification, a cheap promise that can deliver the value if asked, and lets that promise sit untouched, possibly forever, until something downstream consumes it. Four commitments define the move: decouple the moment a computation is specified from the moment it is performed; bind the timing of the work to demand from downstream rather than to input availability; record the result once produced so the work is not repeated; and tolerate the possibility that the work is never needed and so never done at all. The computing machinery, call-by-need, thunks, memoization, streams, generators, makes this exact and composable, but the underlying structural move is older and broader than any programming language. Across substrates the same three elements travel together: a specification of work that could be done, a trigger that pulls work into actual execution only on demand, and a commitment-deferral that buys time, preserves optionality, and avoids paying for work that turns out to be unnecessary, none of which is computational in essence. The structural dual is eager evaluation, which computes everything up front regardless of need; the two form a clean trade-off pair, and seeing them as a pair makes the choice visible. Lazy pays a small bookkeeping cost, the deferred specification must be held and tracked, in exchange for potentially saving the much larger cost of work never demanded plus the optionality of doing the work later with better information. Eager pays full computation cost immediately to avoid bookkeeping and have results ready instantly. Neither dominates; the right choice depends on how often the work is demanded, how costly waiting at force-time is, and how much intervening information improves the deferred work.

Broad Use

  • Programming languages: call-by-need, thunks, generators, promises, and lazy loading of attributes and assets.
  • Build systems: a target is rebuilt only when its output is required and its inputs have changed.
  • Manufacturing: Just-In-Time production makes the part when the next station's kanban card pulls for it.
  • Supply chain: drop-shipping, print-on-demand, and late differentiation postpone the SKU-distinguishing step until an order arrives.
  • Finance: pay-on-delivery and revolving credit drawn only when needed.
  • Biology: inducible gene expression — the lac operon synthesises its enzyme only when lactose is present.
  • Law: the ripeness doctrine defers rulings until an actual controversy arises.

Clarity

Turns a vague "we'll get to it later" into a precise design question with four named parts: the deferred specification, the demand trigger, what the deferral buys, and what it costs.

Manages Complexity

Collapses the worst-case work that could be done into the work actually demanded — often a tiny fraction — so the system never reasons about, schedules, or stores the vast space of unrequested work.

Abstract Reasoning

Trains a reasoner to separate the specification of work from its execution, to find the demand signal that pulls one into the other, and to ask whether deferred work might be needed never (a near-pure win) or eventually (worth it only if the wait improves the work).

Knowledge Transfer

  • Manufacturing: the kanban card is the demand trigger, production sized to the pull, with no work-in-process on never-ordered variants.
  • Finance: real options defer commitment until bad scenarios are eliminated, paying a holding cost for better-informed action.
  • Biology: substrate presence triggers transcription, saving the cell from synthesising an enzyme it cannot use.

Example

The infinite Fibonacci stream fibs = 0 : 1 : zipWith (+) fibs (tail fibs): take 10 fibs forces exactly ten thunks; the eleventh and all beyond are specified but never executed, converting an impossible eager computation into a tractable demand-pulled one.

Relationships to Other Primes

One-hop neighborhood: parents above, mutual partners to the right, children below.Lazy Evaluationsubsumption: PostponementPostponement

Parents (1) — more general patterns this builds on

  • Lazy Evaluation is a kind of Postponement — Genus-species, asserted by both files. lazy_evaluation's What-It-Is-Not: "Postponement delays a committing step to a later, better-informed moment... lazy evaluation binds execution to downstream demand specifically... a narrower, demand-triggered discipline." postponement's frontmatter lists "late binding/lazy eval" as an instance and its own What-It-Is-Not does NOT sever lazy_evaluation. Direction: lazy_evaluation is the narrower demand-triggered species of disciplined deferral. postponement is a real candidate slug. Medium (not high) because lazy_evaluation's optional never-execute path is a genuine differentiator absent from postponement's latest-responsible-moment binding. NOT a reparent to allocation (0.879 nearest, unrelated). Distinct from caching/future_or_promise/optionality per the file.

Path to root: Lazy EvaluationPostponementOptionalityUncertainty

Not to Be Confused With

  • Lazy Evaluation is not Caching because lazy evaluation avoids computing in the first place until demand arrives, whereas caching stores a result already computed — the laziness win is non-execution, not result reuse.
  • Lazy Evaluation is not Future or Promise because lazy evaluation is pull-driven (work may never run), whereas a future reifies a result a producer is committed to supply, often already running.
  • Lazy Evaluation is not Optionality because lazy evaluation is a mechanism that binds execution to demand, whereas optionality is a held right to act later, valuable in itself.