Skip to content

Short-Circuit Evaluation

Evaluation method — instantiates Demand-Triggered Deferred Evaluation

Evaluates a boolean expression left to right and stops the instant the result is settled, so later operands — and their side effects — never run.

Short-circuit evaluation evaluates the operands of a boolean expression left to right and stops the instant the outcome is settled: for A && B, if A is false the whole expression is false and B is never evaluated; for A || B, if A is true, B is skipped. The deferred — and here, entirely skipped — work is the evaluation of the later operand. What makes it THIS mechanism is that skipping is driven purely by the running result of a fixed left-to-right order, with no counters, caches, or thresholds, so the second operand's cost, side effects, and even its ability to fail are all conditional on the first operand not having already decided the answer.

Example

A permission check reads user != null && user.isActive() && user.hasRole("editor"). If user is null, evaluation stops at the first operand — user.isActive() is never called, so no null-pointer exception is thrown. The short-circuit isn't merely an optimization here; it is what makes the guard correct, because the later operands are only safe to evaluate once the earlier ones have vouched for them. Reorder the same conditions as user.isActive() && user != null and the guard breaks — the protection depends entirely on the sequence.

A second everyday use trades cost rather than safety: cache.contains(key) || expensiveLoad(key) runs the expensive load only when the cheap check misses.

How it works

  • Fix an order. Operands evaluate strictly left to right.
  • Stop when decided. For &&, stop at the first falsy operand; for ||, at the first truthy one — the rest are never evaluated.
  • Guard with sequence. Because a later operand runs only if the earlier ones held, an earlier operand can protect a later one (null checks, bounds checks) that would otherwise fault.
  • Offer a non-short-circuit form. Eager boolean operators (such as & / |) evaluate every operand regardless, for when a later operand's side effect must always happen.

Tuning parameters

  • Operand order — which condition goes first. Put the cheapest or most decisive operand first to skip more — but order is also load-bearing for correctness (guards), so it cannot be freely reordered for speed.
  • Short-circuit vs. eager operator — whether to skip settled operands (&&) or force all of them (&). Skipping saves work; forcing guarantees every operand's side effect fires.
  • Guard vs. compute intent — whether a clause is present to protect the next one or to do work. Mixing the two in one expression is what makes reordering dangerous.

When it helps, and when it misleads

Its strength is cheap guards before expensive or unsafe operations, and skipping costly checks once the answer is known — it is the backbone of null-safe and bounds-safe idioms across nearly every language.

It misleads because the skipped operands' side effects don't fire. Moving a side-effecting call into a short-circuited clause silently drops it — a && logAttempt() that stops logging once an earlier check fails — and reordering operands "for performance" can break a guard the old order was quietly providing. The classic misuse is relying on a mutation or counter increment inside a &&/|| operand and being surprised when it sometimes doesn't happen. The discipline is to keep side effects out of short-circuited operands and to treat operand order as part of the logic, not a free optimization.[1]

How it implements the components

Short-Circuit Evaluation fills the skip-on-decided side of the archetype at expression scale — a predicate gate over ordered operands, with an eager escape — not caching or demand detection:

  • need_predicate — each operand acts as the predicate deciding whether the next operand is needed at all.
  • side_effect_boundary — because unreached operands' effects never fire, effect ordering across &&/|| is a correctness boundary.
  • strictness_escape_hatch — the eager, non-short-circuiting operators that force every operand when a side effect must always run.

It does not push a filter down to a data source — that is Predicate Pushdown — nor route a whole workflow branch on a business condition, which is the Conditional Workflow Gate.

References

[1] Short-circuit boolean evaluation is sometimes called McCarthy evaluation, after John McCarthy, whose early LISP defined the conditional so that only the selected branch is evaluated. The &&/|| semantics are its direct descendants.