See it run
LISPEX
(let* ((x 6) (y (+ x 1))) (* x y))Observed result
OUTPUT
42How to reason about it
- Expansion uses fresh names and hidden built-in helpers, so shadowing a name in your own code cannot change what an expansion means.
- Normalization preserves defined tail positions and source diagnostics.
guardis a fixed core-facing construct for catchable errors, not a general macro facility.
What each written form becomes
| Written form | Core strategy | Pinned boundary |
|---|---|---|
| cond / case | nested if with fresh temporaries, and case uses a hidden eqv? | tail clause preserved, and no cond => |
| and / or | short-circuit nested if | single final operand remains tail |
| when / unless | if plus begin or zero-value values | false path returns zero values |
| named let / do | hygienic letrec loop | recursive application is tail |
| quasiquote | quote plus hidden constructors | bare unquote outside quasiquote is static E1xx |
A common mistake
define-syntax, syntax objects, and arbitrary expansion are rejected.
Keep going
Core Forms holds the shapes these rewrite into, and the manual helps you choose between the conditionals.