Binding is lexically scoped assignment. It happens to the variables in a function's parameter list whenever the function is called: the formal parameters are bound to the actual parameters for the duration of the function call. You can bind variables anywhere in a program with the let special form, which looks like this:
(let ((var1 val1)
(var2 val2)
...
)
body)
(It's considered bad style to leave a single ``)'' on a line)
Let binds var1
to val1
, var2
to val2
, and so
forth; then it executes
the statements in its body. The body of a let follows exactly the same
rules that a function body does. Some examples:
> (let ((a 3)) (+ a 1))
4
> (let ((a 2)
(b 3)
(c 0))
(setq c (+ a b))
c)
5
> (setq c 4)
4 ;and a warning from CMUCL, ignore it
> (let ((c 5)) c)
5
> c
4
Instead of (let ((a nil) (b nil)) ...)
, you can write (let (a b) ...)
.
The val1
, val2
, etc. inside a let cannot reference the
variables var1
,
var2
, etc. that the let is binding. For example,
> (let ((x 1)
(y (+ x 1)))
y)
Error: Attempt to take the value of the unbound symbol X
;in CMUCL:
In: LET ((X 1) (Y (+ X 1)))
(LET ((X 1) (Y #))
Y)
Warning: Variable X defined but never used.
Warning: This variable is undefined:
X
Error in KERNEL::UNBOUND-SYMBOL-ERROR-HANDLER: the variable X is
unbound.
Restarts:
0: [ABORT] Return to Top-Level.
Debug (type H for help)
(EVAL::LEAF-VALUE
#<C::REF #x9009B15 LEAF= #<C::GLOBAL-VAR #x9009AD5 NAME= X KIND=
:GLOBAL>>
0
#())
0]
If the symbol x
already has a global value, stranger happenings will
result:
> (setq x 7)
7 ;again a warning in CMUCL:
Warning: Declaring X special.
;x is automaticly declared special
> (let ((x 1)
(y (+ x 1)))
y
)
8
The let*
special form is just like let
except that it allows
values to
reference variables defined earlier in the let*
. For example,
> (setq x 7)
7
> (let* ((x 1)
(y (+ x 1)))
y
)
2
The form
(let* ((x a)
(y b))
...
)
is equivalent to
(let ((x a))
(let ((y b))
...
) )