Prev Up Next

Local variables can be introduced without explicitly creating a procedure. The special form let introduces a list of local variables for use within its body:

(let ((x 1)
      (y 2)
      (z 3))
  (list x y z))
=> (1 2 3)

As with lambda, within the let-body, the local x (bound to 1) shadows the global x (which is bound to 20).

The local variable initializations -- x to 1; y to 2; z to 3 -- are not considered part of the let body. Therefore, a reference to x in the initialization will refer to the global, not the local x:

(let ((x 1)
      (y x))
  (+ x y))
=> 21

This is because x is bound to 1, and y is bound to the global x, which is 20.

Sometimes, it is convenient to have let's list of lexical variables be introduced in sequence, so that the initialization of a later variable occurs in the lexical scope of earlier variables. The form let* does this:

(let* ((x 1)
       (y x))
  (+ x y))
=> 2

The x in y's initialization refers to the x just above. The example is entirely equivalent to -- and is in fact intended to be a convenient abbreviation for -- the following program with nested lets:

(let ((x 1))
  (let ((y x))
    (+ x y)))
=> 2

The values bound to lexical variables can be procedures:

(let ((cons (lambda (x y) (+ x y))))
  (cons 1 2))
=> 3

Inside this let body, the lexical variable cons adds its arguments. Outside, cons continues to create dotted pairs.

Prev Up Next