7.5 Establishing New Variable Bindings

During the invocation of a function represented by a lambda-expression (or a closure of a lambda-expression, as produced by function), new bindings are established for the variables that are the parameters of the lambda-expression. These bindings initially have values determined by the parameter-binding protocol discussed in section 5.2.2.

The following constructs may also be used to establish bindings of variables, both ordinary and functional.

[Special operator] let ({var | (var [value])}*) {declaration}* {form}*

A let form can be used to execute a series of forms with specified variables bound to specified values.

More precisely, the form

(let ((var1 value1)
      (var2 value2)
      ...
      (varm valuem))
  declaration1
  declaration2
  ...
  declarationp
  body1
  body2
  ...
  bodyn)

first evaluates the expressions value1, value2, and so on, in that order, saving the resulting values. Then all of the variables varj are bound to the corresponding values in parallel; each binding will be a lexical binding unless there is a special declaration to the contrary. The expressions bodyk are then evaluated in order; the values of all but the last are discarded (that is, the body of a let form is an implicit progn). The let form returns what evaluating bodyn produces (if the body is empty, which is fairly useless, let returns nil as its value). The bindings of the variables have lexical scope and indefinite extent.

Instead of a list (varj valuej), one may write simply varj. In this case varj is initialized to nil. As a matter of style, it is recommended that varj be written only when that variable will be stored into (such as by setq) before its first use. If it is important that the initial value be nil rather than some undefined value, then it is clearer to write out (varj nil) if the initial value is intended to mean “false,” or (varj ’()) if the initial value is intended to be an empty list. Note that the code

(let (x)
  (declare (integer x))
  (setq x (gcd y z))
  ...)

is incorrect; although x is indeed set before it is used, and is set to a value of the declared type integer, nevertheless x momentarily takes on the value nil in violation of the type declaration.

Declarations may appear at the beginning of the body of a let. See declare.

See also destructuring-bind.


[Special operator] let* ({var | (var [value])}*) {declaration}* {form}*

let* is similar to let, but the bindings of variables are performed sequentially rather than in parallel. This allows the expression for the value of a variable to refer to variables previously bound in the let* form.

More precisely, the form

(let* ((var1 value1)
       (var2 value2)
       ...
       (varm valuem))
  declaration1
  declaration2
  ...
  declarationp
  body1
  body2
  ...
  bodyn)

first evaluates the expression value1, then binds the variable var1 to that value; then it evaluates value2 and binds var2; and so on. The expressions bodyj are then evaluated in order; the values of all but the last are discarded (that is, the body of a let* form is an implicit progn). The let* form returns the results of evaluating bodyn (if the body is empty, which is fairly useless, let* returns nil as its value). The bindings of the variables have lexical scope and indefinite extent.

Instead of a list (varj valuej), one may write simply varj. In this case varj is initialized to nil. As a matter of style, it is recommended that varj be written only when that variable will be stored into (such as by setq) before its first use. If it is important that the initial value be nil rather than some undefined value, then it is clearer to write out (varj nil) if the initial value is intended to mean “false,” or (varj ’()) if the initial value is intended to be an empty list.

Declarations may appear at the beginning of the body of a let*. See declare.


[Special operator] progv symbols values {form}*

progv is a special operator that allows binding one or more dynamic variables whose names may be determined at run time. The sequence of forms (an implicit progn) is evaluated with the dynamic variables whose names are in the list symbols bound to corresponding values from the list values. (If too few values are supplied, the remaining symbols are bound and then made to have no value; see makunbound. If too many values are supplied, the excess values are ignored.) The results of the progv form are those of the last form. The bindings of the dynamic variables are undone on exit from the progv form. The lists of symbols and values are computed quantities; this is what makes progv different from, for example, let, where the variable names are stated explicitly in the program text.

progv is particularly useful for writing interpreters for languages embedded in Lisp; it provides a handle on the mechanism for binding dynamic variables.


[Special operator] flet ({(name lambda-list[[{declaration}* | doc-string]] {form}*)}*){declaration}* {form}*

[Special operator] labels ({(name lambda-list[[{declaration}* | doc-string]] {form}*)}*){declaration}* {form}*

[Special operator] macrolet ({(name varlist[[{declaration}* | doc-string]] {form}*)}*){declaration}* {form}*

flet may be used to define locally named functions. Within the body of the flet form, function names matching those defined by the flet refer to the locally defined functions rather than to the global function definitions of the same name.

Any number of functions may be simultaneously defined. Each definition is similar in format to a defun form: first a name, then a parameter list (which may contain &optional, &rest, or &key parameters), then optional declarations and documentation string, and finally a body.

(flet ((safesqrt (x) (sqrt (abs x))))
  ;; The safesqrt function is used in two places.
  (safesqrt (apply #’+ (map ’list #’safesqrt longlist))))

The labels construct is identical in form to the flet construct. These constructs differ in that the scope of the defined function names for flet encompasses only the body, whereas for labels it encompasses the function definitions themselves. That is, labels can be used to define mutually recursive functions, but flet cannot. This distinction is useful. Using flet one can locally redefine a global function name, and the new definition can refer to the global definition; the same construction using labels would not have that effect.

(defun integer-power (n k)       ;A highly "bummed" integer
  (declare (integer n))          ; exponentiation routine
  (declare (type (integer 0 *) k))
  (labels ((expt0 (x k a)
             (declare (integer x a) (type (integer 0 *) k))
             (cond ((zerop k) a)
                   ((evenp k) (expt1 (* x x) (floor k 2) a))
                   (t (expt0 (* x x) (floor k 2) (* x a)))))
           (expt1 (x k a)
             (declare (integer x a) (type (integer 1 *) k))
             (cond ((evenp k) (expt1 (* x x) (floor k 2) a))
                   (t (expt0 (* x x) (floor k 2) (* x a))))))
    (expt0 n k 1)))

macrolet is similar in form to flet but defines local macros, using the same format used by defmacro. The names established by macrolet as names for macros are lexically scoped.

I have observed that, while most Common Lisp users pronounce macrolet to rhyme with “silhouette,” a small but vocal minority pronounce it to rhyme with “Chevrolet.” A very few extremists furthermore adjust their pronunciation of flet similarly: they say “flay.” Hey, hey! Tr`es outr´e.

Macros often must be expanded at “compile time” (more generally, at a time before the program itself is executed), and so the run-time values of variables are not available to macros defined by macrolet.

X3J13 voted in March 1989 to retract the previous sentence and specify that the macro-expansion functions created by macrolet are defined in the lexical environment in which the macrolet form appears, not in the null lexical environment. Declarations, macrolet definitions, and symbol-macrolet definitions affect code within the expansion functions in a macrolet, but the consequences are undefined if such code attempts to refer to any local variable or function bindings that are visible in that lexical environment.

However, lexically scoped entities are visible within the body of the macrolet form and are visible to the code that is the expansion of a macro call. The following example should make this clear:

;;; Example of scoping in macrolet.

(defun foo (x flag)
  (macrolet ((fudge (z)
                ;;The parameters x and flag are not accessible
                ;; at this point; a reference to flag would be to
                ;; the global variable of that name.
                ‘(if flag
                     (* ,z ,z)
                     ,z)))
    ;;The parameters x and flag are accessible here.
    (+ x
       (fudge x)
       (fudge (+ x 1)))))

The body of the macrolet becomes

(+ x
   (if flag
       (* x x)
       x))
   (if flag
       (* (+ x 1) (+ x 1))
       (+ x 1)))

after macro expansion. The occurrences of x and flag legitimately refer to the parameters of the function foo because those parameters are visible at the site of the macro call which produced the expansion.

The body of each function or expander function defined by flet, labels, or macrolet is implicitly enclosed in a block construct whose name is the same as the name of the function. Therefore return-from may be used to exit from the function.

flet and labels accept any function-name (a symbol or a list whose car is setf—see section 7.1) as a name for a function to be locally defined. In this way one can create local definitions for setf expansion functions. (X3J13 explicitly declined to extend macrolet in the same manner.)

X3J13 voted in March 1988 to change flet, labels, and macrolet to allow declarations to appear before the body. The new descriptions are therefore as follows:


[Special operator] symbol-macrolet ({(var expansion)}*){declaration}* {form}*

X3J13 voted in June 1988 to adopt the Common Lisp Object System. Part of this proposal is a general mechanism, symbol-macrolet, for treating certain variable names as if they were parameterless macro calls. This facility may be useful independent of CLOS. X3J13 voted in March 1989 to modify the definition of symbol-macrolet substantially and also voted to allow declarations before the body of symbol-macrolet but with peculiar treatment of special and type declarations.

The forms are executed as an implicit progn in a lexical environment that causes every reference to any defined var to be replaced by the corresponding expansion. It is as if the reference to the var were a parameterless macro call; the expansion is evaluated or otherwise processed in place of the reference (in particular, the expansion form is itself subject to further expansion—this is one of the changes from the original definition in the CLOS proposal). Note, however, that the names of such symbol macros occupy the name space of variables, not the name space of functions; just as one may have a function (or macro, or special operator) and a variable with the same name without interference, so one may have an ordinary macro (or function, or special operator) and a symbol macro with the same name. The use of symbol-macrolet can therefore be shadowed by let or other constructs that bind variables; symbol-macrolet does not substitute for all occurrences of a var as a variable but only for those occurrences that would be construed as references in the scope of a lexical binding of var as a variable. For example:

(symbol-macrolet ((pollyanna ’goody))
  (list pollyanna (let ((pollyanna ’two-shoes)) pollyanna)))
  (goody two-shoes), not (goody goody)

One might think that ’goody simply replaces all occurrences of pollyanna, and so the value of the let would be goody; but this is not so. A little reflection shows that under this incorrect interpretation the body in expanded form would be

(list ’goody (let ((’goody ’two-shoes)) ’goody))

which is syntactically malformed. The correct expanded form is

(list ’goody (let ((pollyanna ’two-shoes)) pollyanna))

because the rebinding of pollyanna by the let form shadows the symbol macro definition.

The expansion for each var is not evaluated at binding time but only after it has replaced a reference to the var. The setf macro allows a symbol macro to be used as a place, in which case its expansion is used; moreover, setq of a variable that is really a symbol macro will be treated as if setf had been used. The values of the last form are returned, or nil if there is no value.

See macroexpand and macroexpand-1; they will expand symbol macros as well as ordinary macros.

Certain declarations before the body are handled in a peculiar manner; see section 9.1.


[Macro] define-symbol-macro symbol {form}

The symbol will act as a macro call. A single form constitutes the body of the expansion. The symbol cannot already be a special variable.