Common Lisp the Language, 2nd Edition


next up previous contents index
Next: Assignment Up: Constants and Variables Previous: Constants and Variables

7.1. Reference

The value of an ordinary variable may be obtained simply by writing the name of the variable as a form to be executed. Whether this is treated as the name of a special variable or a lexical variable is determined by the presence or absence of an applicable special declaration; see chapter 9.

The following functions and special forms allow reference to the values of constants and variables in other ways.


[Special Form]
quote object

(quote x) simply returns x. The object is not evaluated and may be any Lisp object whatsoever. This construct allows any Lisp object to be written as a constant value in a program. For example:

(setq a 43) 
(list a (cons a 3)) => (43 (43 . 3)) 
(list (quote a) (quote (cons a 3)) => (a (cons a 3))

Since quote forms are so frequently useful but somewhat cumbersome to type, a standard abbreviation is defined for them: any form f preceded by a single quote (') character is assumed to have (quote ) wrapped around it to make (quote f). For example:

(setq x '(the magic quote hack))

is normally interpreted by read to mean

(setq x (quote (the magic quote hack)))

See section 22.1.3.

change_begin
X3J13 voted in January 1989 (CONSTANT-MODIFICATION)   to clarify that it is an error to destructively modify any object that appears as a constant in executable code, whether within a quote special form or as a self-evaluating form.

See section 25.1 for a discussion of how quoted constants are treated by the compiler.

X3J13 voted in March 1989 (QUOTE-SEMANTICS)   to clarify that eval and compile are not permitted either to copy or to coalesce (``collapse'') constants (see eq) appearing in the code they process; the resulting program behavior must refer to objects that are eql to the corresponding objects in the source code. Moreover, the constraints introduced by the votes on issues (CONSTANT-COMPILABLE-TYPES)   and (CONSTANT-CIRCULAR-COMPILATION)   on what kinds of objects may appear as constants apply only to compile-file (see section 25.1).
change_end


[Special Form]
function fn

The value of function is always the functional interpretation of fn; fn is interpreted as if it had appeared in the functional position of a function invocation. In particular, if fn is a symbol, the functional definition associated with that symbol is returned; see symbol-function. If fn is a lambda-expression, then a ``lexical closure'' is returned, that is, a function that when invoked will execute the body of the lambda-expression in such a way as to observe the rules of lexical scoping properly.

change_begin
X3J13 voted in June 1988 (FUNCTION-TYPE)   to specify that the result of a function special form is always of type function. This implies that a form (function fn) may be interpreted as (the (function fn)).

It is an error to use the function special form on a symbol that does not denote a function in the lexical or global environment in which the special form appears. Specifically, it is an error to use the function special form on a symbol that denotes a macro or special form. Some implementations may choose not to signal this error for performance reasons, but implementations are forbidden to extend the semantics of function in this respect; that is, an implementation is not allowed to define the failure to signal an error to be a ``useful'' behavior.

X3J13 voted in March 1989 (FUNCTION-NAME)   to extend function to accept any function-name (a symbol or a list whose car is setf-see section 7.1) as well as lambda-expressions. Thus one may write (function (setf cadr)) to refer to the setf expansion function for cadr.
change_end

  For example:

(defun adder (x) (function (lambda (y) (+ x y))))

The result of (adder 3) is a function that will add 3 to its argument:

(setq add3 (adder 3)) 
(funcall add3 5) => 8

This works because function creates a closure of the inner lambda-expression that is able to refer to the value 3 of the variable x even after control has returned from the function adder.

More generally, a lexical closure in effect retains the ability to refer to lexically visible bindings, not just values. Consider this code:

(defun two-funs (x) 
  (list (function (lambda () x)) 
        (function (lambda (y) (setq x y))))) 
(setq funs (two-funs 6)) 
(funcall (car funs)) => 6 
(funcall (cadr funs) 43) => 43 
(funcall (car funs)) => 43

The function two-funs returns a list of two functions, each of which refers to the binding of the variable x created on entry to the function two-funs when it was called with argument 6. This binding has the value 6 initially, but setq can alter a binding. The lexical closure created for the first lambda-expression does not ``snapshot'' the value 6 for x when the closure is created. The second function can be used to alter the binding (to 43, in the example), and this altered value then becomes accessible to the first function.

In situations where a closure of a lambda-expression over the same set of bindings may be produced more than once, the various resulting closures may or may not be eq, at the discretion of the implementation. For example:

(let ((x 5) (funs '())) 
  (dotimes (j 10) 
    (push #'(lambda (z) 
              (if (null z) (setq x 0) (+ x z))) 
          funs)) 
  funs)

The result of the above expression is a list of ten closures. Each logically requires only the binding of x. It is the same binding in each case, so the ten closures may or may not be the same identical (eq) object. On the other hand, the result of the expression

(let ((funs '())) 
  (dotimes (j 10) 
    (let ((x 5)) 
      (push (function (lambda (z) 
                        (if (null z) (setq x 0) (+ x z)))) 
            funs))) 
  funs)

is also a list of ten closures. However, in this case no two of the closures may be eq, because each closure is over a distinct binding of x, and these bindings can be behaviorally distinguished because of the use of setq.

The question of distinguishable behavior is important; the result of the simpler expression

(let ((funs '())) 
  (dotimes (j 10) 
    (let ((x 5)) 
      (push (function (lambda (z) (+ x z))) 
            funs))) 
  funs)

is a list of ten closures that may be pairwise eq. Although one might think that a different binding of x is involved for each closure (which is indeed the case), the bindings cannot be distinguished because their values are identical and immutable, there being no occurrence of setq on x. A compiler would therefore be justified in transforming the expression to

(let ((funs '())) 
  (dotimes (j 10) 
    (push (function (lambda (z) (+ 5 z))) 
          funs)) 
  funs)

where clearly the closures may be the same after all. The general rule, then, is that the implementation is free to have two distinct evaluations of the same function form produce identical (eq) closures if it can prove that the two conceptually distinct resulting closures must in fact be behaviorally identical with respect to invocation. This is merely a permitted optimization; a perfectly valid implementation might simply cause every distinct evaluation of a function form to produce a new closure object not eq to any other.

Frequently a compiler can deduce that a closure in fact does not need to close over any variable bindings. For example, in the code fragment

(mapcar (function (lambda (x) (+ x 2))) y)

the function (lambda (x) (+ x 2)) contains no references to any outside entity. In this important special case, the same ``closure'' may be used as the value for all evaluations of the function special form. Indeed, this value need not be a closure object at all; it may be a simple compiled function containing no environment information. This example is simply a special case of the foregoing discussion and is included as a hint to implementors familiar with previous methods of implementing Lisp. The distinction between closures and other kinds of functions is somewhat pointless, actually, as Common Lisp defines no particular representation for closures and no way to distinguish between closures and non-closure functions. All that matters is that the rules of lexical scoping be obeyed.

Since function forms are so frequently useful but somewhat cumbersome to type, a standard abbreviation is defined for them: any form f preceded by #' (# followed by an apostrophe) is assumed to have (function ) wrapped around it to make (function f). For example,

(remove-if #'numberp '(1 a b 3))

is normally interpreted by read to mean

(remove-if (function numberp) '(1 a b 3))

See section 22.1.4.


[Function]
symbol-value symbol

symbol-value returns the current value of the dynamic (special) variable named by symbol. An error occurs if the symbol has no value; see boundp and makunbound. Note that constant symbols are really variables that cannot be changed, and so symbol-value may be used to get the value of a named constant. In particular, symbol-value of a keyword will return that keyword.

symbol-value cannot access the value of a lexical variable.

This function is particularly useful for implementing interpreters for languages embedded in Lisp. The corresponding assignment primitive is set; alternatively, symbol-value may be used with setf.


[Function]
symbol-function symbol

symbol-function returns the current global function definition named by symbol. An error is signalled if the symbol has no function definition; see fboundp. Note that the definition may be a function or may be an object representing a special form or macro. In the latter case, however, it is an error to attempt to invoke the object as a function. If it is desired to process macros, special forms, and functions equally well, as when writing an interpreter, it is best first to test the symbol with macro-function and special-form-p and then to invoke the functional value only if these two tests both yield false.

This function is particularly useful for implementing interpreters for languages embedded in Lisp.

symbol-function cannot access the value of a lexical function name produced by flet or labels; it can access only the global function value.

The global function definition of a symbol may be altered by using setf with symbol-function. Performing this operation causes the symbol to have only the specified definition as its global function definition; any previous definition, whether as a macro or as a function, is lost. It is an error to attempt to redefine the name of a special form (see table 5-1).

change_begin
X3J13 voted in June 1988 (FUNCTION-TYPE)   to clarify the behavior of symbol-function in the light of the redefinition of the type function.


change_end

change_begin

[Function]
fdefinition function-name

X3J13 voted in March 1989 (FUNCTION-NAME)   to add the function fdefinition to the language. It is exactly like symbol-function except that its argument may be any function-name (a symbol or a list whose car is setf-see section 7.1); it returns the current global function definition named by the argument function-name. One may use fdefinition with setf to change the current global function definition associated with a function-name.
change_end


[Function]
boundp symbol

boundp is true if the dynamic (special) variable named by symbol has a value; otherwise, it returns nil.

See also set and makunbound.


[Function]
fboundp symbol

fboundp is true if the symbol has a global function definition. Note that fboundp is true when the symbol names a special form or macro. macro-function and special-form-p may be used to test for these cases.

change_begin
X3J13 voted in June 1988 (FUNCTION-TYPE)   to emphasize that, despite the tightening of the definition of the type function, fboundp must return true when the argument names a special form or macro.

See also symbol-function and fmakunbound.

X3J13 voted in March 1989 (FUNCTION-NAME)   to extend fboundp to accept any function-name (a symbol or a list whose car is setf-see section 7.1). Thus one may write (fboundp '(setf cadr)) to determine whether a setf expansion function has been globally defined for cadr.
change_end


[Function]
special-form-p symbol

The function special-form-p takes a symbol. If the symbol globally names a special form, then a non-nil value is returned; otherwise nil is returned. A returned non-nil value is typically a function of implementation-dependent nature that can be used to interpret (evaluate) the special form.

It is possible for both special-form-p and macro-function to be true of a symbol. This is possible because an implementation is permitted to implement any macro also as a special form for speed. On the other hand, the macro definition must be available for use by programs that understand only the standard special forms listed in table 5-1.



next up previous contents index
Next: Assignment Up: Constants and Variables Previous: Constants and Variables


AI.Repository@cs.cmu.edu