When this matters
Create a procedure when one transformation has a name or must be passed to another procedure. Named shorthand is easiest to read. lambda is useful when the behavior is small and local.
See it run
(define (sum first . rest) (apply + first rest))
(sum 1 2 3 4)Observed result
10Read the example
sum requires at least one argument. first receives 1, while rest receives the fresh list (2 3 4). apply combines the explicit first argument with that list and invokes + once.
A run of define forms at the very start of a procedure body creates names visible only inside that procedure. They can call each other.
(define (g)
(define a 1)
(define b 2)
(+ a b))
(g)Observed result
3Only the unbroken run at the start is grouped this way. A define that comes after some other expression means something different, so keep the definitions together at the top.
How to reason about it
- Arity mismatch is E302 before the procedure body starts.
- A dotted rest parameter receives a fresh proper list of remaining arguments.
- A
lambdaparameter list has exactly two shapes,(x ...)and(x ... . rest). A bare name with no parentheses, as in(lambda args ...), is E130. applyaccepts explicit leading arguments plus one final proper list and preserves tail position.
Choose quickly
| Shape | Best use | Arity |
|---|---|---|
(define (f x) body) | a named reusable procedure | fixed |
(lambda (x y) body) | an anonymous procedure value | fixed |
(define (f . xs) body) | a named procedure that gathers its arguments | zero or more |
(lambda (x . rest) body) | required arguments plus a remainder | at least the fixed prefix |
(apply f a final-list) | arguments assembled as data | checked by f |
A common mistake
Applying a non-procedure is E301. An improper final apply list is a list-domain error.
Current boundaries
- Host
applyis not used to execute guest closures.
Keep going
Higher-order procedures explains passing behavior to map, filter, and fold. Bindings explains the cells a closure captures.