Conditionals and Derived Forms

A small core of if, sequencing, binding, lambda, application, assignment, and quotation receives derived forms that are rewritten without ever capturing the names you chose.

When this matters

Choose a conditional by the shape of the question. It may be one yes/no test, several predicates, one value compared with fixed datums, or a side effect that should run only in one case. Remember that only #f is false.

See it run

LISPEX
(case 2 ((1) 'one) ((2) 'two) (else 'other))

Observed result

OUTPUT
two

Read the example

case evaluates 2 once, compares it with each listed datum using eqv?, and selects the second clause. The quoted symbol two is the result, and the else clause is not evaluated.

when runs its body in order only when the test is true and gives back the last value. unless does the opposite and runs when the test is false. So (when #t 42) is 42 and (unless #f 7) is 7. The path the test rules out produces no value at all.

guard is written (guard (variable clause ...) body ...). When the body raises, the error object is bound to the variable and the clauses are tried in order the way cond tries them. A clause head may be else.

How to reason about it

  • cond, case, and, or, when, unless, let*, named let, do, and quasiquote preserve pinned evaluation and tail positions.
  • Generated temporary names and hidden built-in operations cannot be captured or shadowed by user names.
  • case compares datums with eqv?, and the false paths of when and unless produce zero values.
  • if needs all three parts. Drop the false arm and write (if #t 1) and you get E130.
  • A cond or case with no else clause produces no value at all when nothing matches. Put that result where a value is required and you get E320.
  • else is not a reserved word. It only means something at the head of a cond, case, or guard clause, so (define else 5) is accepted.
  • The cond arrow clause => is not supported and raises E130. The case arrow clause has no diagnostic at all, so => reads as a name and raises E300.

Choose quickly

FormUse it whenResult behavior
ifthere are exactly two branchesreturns the selected branch
conddifferent predicates name several casesreturns the first matching clause
caseone value is compared with fixed datumsevaluates the key once
and / ortests form a short-circuit chainreturns an operand value, not a coerced boolean
when / unlessa one-sided effect is clearerfalse path returns zero values

A common mistake

There is no define-syntax or user macro expansion.

Current boundaries

  • Bare unquote and unquote-splicing outside quasiquote are static errors.

Keep going

The data-and-decisions lesson teaches the everyday forms. Derived Forms gives their exact normalization shapes.

Data and decisions · Derived Forms