Go to the first, previous, next, last section, table of contents.

Lexical Scope

If nested lets define variables by the same name, then the uses of that name in the body of the inner let will refer to the bindings created by the inner let.

Consider the following code fragment:

(let ((x 10)    ; outer binding of x
      (a 20))   ; binding of a
   (foo x)
   (let ((x (bar))       ; inner binding of x
         (b (baz x x)))  ; binding of b
      (quux x a)
      (quux y b))
   (baz x a)  ; refers to outer x (and a)
   (baz x b)) ; illegal?

When control enters the outer let, the inital values for the variables are computed. In this case, that's just the literal values 10 and 20. Then storage is allocated for the variables, and initialized with those values. Once that's done, the meaning of the names x and a changes--they now refer to the new storage for (bindings of) the let variables x and a---and then the body expressions are evaluated.

Similarly, when control enters the inner let, the inital values are computed by the calls to bar and baz, and then storage for x and b is allocated and initialized with those values. Then the meanings of the names x and b change, to refer to the new storage (bindings) of those variables. (For example, the value of x when (baz x x) is evaluated is still 10, because x still refers to the outer x.)

In this example, the meaning of the identifier x changes when we enter the inner let. We say that the inner let variable x shadows the outer one, within the body of the let. The outer x is no longer visible, because the inner one is.

When we exit a let (after evaluating its body expressions), the bindings introduced by the let "go out of scope," i.e., aren't visible anymore. (For example, when we evaluate the expression (baz x a) in the body of the outer let, x refers to the binding introduced by the outer let---the x introduced by the inner let is no longer visible.

Likewise, in the example code fragment, the b in the last expression, (baz x b), does not refer to the inner let's binding of b. Unless there is a binding of b in some outer scope we haven't shown (such as a top-level binding), then this will be an error.


Go to the first, previous, next, last section, table of contents.