When this matters
Evaluation order matters whenever expressions mutate a cell, print output, raise an error, or may be skipped. Lispex fixes the order so the same source never depends on a host language’s operand convention.
See it run
LISPEX
(define x 0)
(list (begin (set! x 1) x) (begin (set! x (+ x 1)) x))Observed result
OUTPUT
(1 2)Read the example
The first begin changes x from 0 to 1 and returns 1. Only then does the second operand read that new value, add one, store 2, and return it. list therefore receives 1 followed by 2.
How to reason about it
letinitializers use the enclosing environment left to right;let*extends one binding at a time;letrecallocates all cells first.- Sequences evaluate left to right and discard non-final value packets.
andandorshort-circuit left to right; only#fis false.
Choose quickly
| Context | Order | What may be skipped |
|---|---|---|
| procedure call | operator, then operands left to right | nothing |
begin | forms left to right | nothing; only earlier values are discarded |
if | test, then one selected branch | the unselected branch |
and / or | operands left to right | the remaining operands after the answer is known |
let | initializers left to right in the outer scope | nothing |
let* | bind and extend after each initializer | nothing |
A common mistake
Lispex does not inherit an unspecified operand order from another Scheme implementation.
Current boundaries
- Arity errors occur after already-required operator and operand evaluation.
Keep going
Bindings explains the different let scopes. Conditionals shows which forms deliberately stop early.