#
Chapter 5
Lexical variables

Scheme's variables have lexical scope, ie, they are visible only to forms within a certain contiguous stretch of program text. The global variables we have seen thus far are no exception: Their scope is all program text, which is certainly contiguous.

We have also seen some examples of local variables. These were the `lambda` parameters, which get bound each time the procedure is called, and whose scope is that procedure's body. Eg,

    (define x 9)
    (define add2 (lambda (x) (+ x 2)))

    x        =>  9

    (add2 3) =>  5
    (add2 x) =>  11

    x        =>  9

Here, there is a global `x`, and there is also a local `x`, the latter introduced by procedure `add2`. The global `x` is always `9`. The local `x` gets bound to `3` in the first call to `add2` and to the value of the global `x`, ie, `9`, in the second call to `add2`. When the procedure calls return, the global `x` continues to be `9`.

The form `set!` modifies the lexical binding of a variable.

    (set! x 20)

modifies the global binding of `x` from `9` to `20`, because that is the binding of `x` that is visible to `set!`. If the `set!` was inside `add2`'s body, it would have modified the local `x`:

    (define add2
      (lambda (x)
        (set! x (+ x 2))
        x))

The `set!` here adds `2` to the local variable `x`, and the procedure returns this new value of the local `x`. (In terms of effect, this procedure is indistinguishable from the previous `add2`.) We can call `add2` on the global `x`, as before:

    (add2 x) =>  22

(Remember global `x` is now `20`, not `9`!)

The `set!` inside `add2` affects only the local variable used by `add2`. Although the local variable `x` got its binding from the global `x`, the latter is unaffected by the `set!` to the local `x`.

    x =>  20

Note that we had all this discussion because we used the same identifier for a local variable and a global variable. In any text, an identifier named `x` refers to the lexically closest variable named `x`. This will shadow any outer or global `x`'s. Eg, in `add2`, the parameter `x` shadows the global `x`.

A procedure's body can access and modify variables in its surrounding scope provided the procedure's parameters don't shadow them. This can give some interesting programs. Eg,

    (define counter 0)

    (define bump-counter
      (lambda ()
        (set! counter (+ counter 1))
        counter))

The procedure `bump-counter` is a zero-argument procedure (also called a thunk). It introduces no local variables, and thus cannot shadow anything. Each time it is called, it modifies the global variable `counter` -- it increments it by 1 -- and returns its current value. Here are some successive calls to `bump-counter`:

    (bump-counter) =>  1
    (bump-counter) =>  2
    (bump-counter) =>  3

## 5.1 `let` and `let*`

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 `let`s:

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

## 5.2 `fluid-let`

A lexical variable is visible throughout its scope, provided it isn't shadowed. Sometimes, it is helpful to temporarily set a lexical variable to a certain value. For this, we use the form `fluid-let`.2

    (fluid-let ((counter 99))
      (display (bump-counter)) (newline)
      (display (bump-counter)) (newline)
      (display (bump-counter)) (newline))

This looks similar to a `let`, but instead of shadowing the global variable `counter`, it temporarily sets it to `99` before continuing with the `fluid-let` body. Thus the `display`s in the body produce

    100
    101
    102

After the `fluid-let` expression has evaluated, the global `counter` reverts to the value it had before the `fluid-let`.

    counter =>  3

Note that `fluid-let` has an entirely different effect from `let`. `fluid-let` does not introduce new lexical variables like `let` does. It modifies the bindings of existing lexical variables, and the modification ceases as soon as the `fluid-let` does.

To drive home this point, consider the program

    (let ((counter 99))
      (display (bump-counter)) (newline)
      (display (bump-counter)) (newline)
      (display (bump-counter)) (newline))

which substitutes `let` for `fluid-let` in the previous example. The output is now

    4
    5
    6

Ie, the global `counter`, which is initially `3`, is updated by each call to `bump-counter`. The new lexical variable `counter`, with its initialization of `99`, has no impact on the calls to `bump-counter`, because although the calls to `bump-counter` are within the scope of this local `counter`, the body of `bump-counter` isn't. The latter continues to refer to the global `counter`, whose final value is `6`.

    counter =>  6

2 `fluid-let` is a nonstandard special form. See sec 8.3 for a definition of `fluid-let` in Scheme.