Scoping

Every symbol may have associated value. A symbol is evaluated to its value determined in the current binding context. There are two kinds of variable bindings; the lexical or static binding and the special or dynamic binding. Lexically bound variables are introduced by lambda form or let and let* special forms unless they are declared special. Lexical binding can be nested and the only one binding which is introduced innermost level is visible, hiding outer lexical bindings and the special binding. Special variables are used in two ways: one is for global variables, and the other is for dynamically scoped local variables which are visible even at the outside of the lexical scope as long as the binding is in effect. In the latter case, special variables are needed to be declared special. The declaration is recognized not only by the compiler, but also by the interpreter. According to the Common Lisp's terms, special variables are said to have indefinite scope and dynamic extent.

Even if there exists a lexical variable in a certain scope, the same variable name can be redeclared to be special in inner scope. Function symbol-value can be used to retrieve the special values regardless to the lexical scopes. Note that set function works only for special variable, i.e. it cannot be used to change the value of lambda or let variables unless they are declared special.

(let ((x 1))
   (declare (special x))
   (let* ((x (+ x x)) (y x))
      (let* ((y (+ y y)) (z (+ x x)))
         (declare (special x))
         (format t "x=~S y=~s z=~s~%" x y z) ) ) )
--> x=1 y=4 z=2

A symbol can be declared to be a constant by defconstant macro. Once declared, an attempt to change the value signals an error thereafter. Moreover, such a constant symbol is inhibited to be used as the name of a variable even for a local variable. NIL and T are examples of such constants. Symbols in the keyword package are always declared to be constants when they are created. In contrast, defvar and defparameter macro declare symbols to be special variables. defvar initializes the value only if the symbol is unbound, and does nothing when it already has a value assigned, while defparameter always resets the value.

When a symbol is referenced and there is no lexical binding for the symbol, its special value is retrieved. However, if no value has been assigned to its special value yet, unbound variable error is signaled.

k-okada 2013-05-21