Common LISP Hints: Binding

## 11. Binding

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))
>               ...
>     ) )

> `