Common Lisp the Language, 2nd Edition

Next: Predicates Up: Top-Level Forms Previous: Declaring Global Variables

## 5.3.3. Control of Time of Evaluation

The `eval-when` special form allows pieces of code to be executed only at compile time, only at load time, or when interpreted but not compiled. Its uses are relatively esoteric.

[Special Form]
`eval-when` `({situation}*)` `{form}*`

The body of an `eval-when` form is processed as an implicit `progn`, but only in the situations listed. Each situation must be a symbol, either `compile`, `load`, or `eval`.

`eval` specifies that the interpreter should process the body. `compile` specifies that the compiler should evaluate the body at compile time in the compilation context. `load` specifies that the compiler should arrange to evaluate the forms in the body when the compiled file containing the `eval-when` form is loaded.

The `eval-when` construct may be more precisely understood in terms of a model of how the compiler processes forms in a file to be compiled. Successive forms are read from the file using the function `read`. These top-level forms are normally processed in what we shall call not-compile-time mode. There is another mode called compile-time-too mode. The `eval-when` special form controls which of these two modes to use.

Every form is processed as follows:

- If the form is an `eval-when` form:

  - If the situation `load` is specified:

    - If the situation `compile` is specified, or if the current processing mode is compile-time-too and the situation `eval` is specified, then process each of the forms in the body in compile-time-too mode.

    - Otherwise, process each of the forms in the body in not-compile-time mode.

  - If the situation `load` is not specified:

    - If the situation `compile` is specified, or if the current processing mode is compile-time-too and the situation `eval` is specified, then evaluate each of the forms in the body in the compiler's executing environment.

    - Otherwise, ignore the `eval-when` form entirely.

- If the form is not an `eval-when` form, then do two things. First, if the current processing mode is compile-time-too mode, evaluate the form in the compiler's executing environment. Second, perform normal compiler processing of the form (compiling functions defined by `defun` forms, and so on).

One example of the use of `eval-when` is that if the compiler is to be able to properly read a file that uses user-defined reader macro characters, it is necessary to write

    (eval-when (compile load eval)
      (set-macro-character #\$ #'(lambda (stream char)
                                   (declare (ignore char))
                                   (list 'dollar (read stream)))))

This causes the call to `set-macro-character` to be executed in the compiler's execution environment, thereby modifying its reader syntax table.

X3J13 voted in March 1989 (EVAL-WHEN-NON-TOP-LEVEL) to completely redesign the `eval-when` construct to solve some problems concerning its treatment in other than top-level contexts. The new definition is upward compatible with the old definition, but the old keywords are deprecated.

[Special Form]
`eval-when` `({situation}*)` `{form}*`

The body of an `eval-when` form is processed as an implicit `progn`, but only in the situations listed. Each situation must be a symbol, either `:compile-toplevel`, `:load-toplevel`, or `:execute`.

The use of `:compile-toplevel` and `:load-toplevel` controls whether and when processing occurs for top-level forms. The use of `:execute` controls whether processing occurs for non-top-level forms.

The `eval-when` construct may be more precisely understood in terms of a model of how the file compiler, `compile-file`, processes forms in a file to be compiled.

Successive forms are read from the file by the file compiler using `read`. These top-level forms are normally processed in what we call ``not-compile-time'' mode. There is one other mode, called ``compile-time-too'' mode, which can come into play for top-level forms. The `eval-when` special form is used to annotate a program in a way that allows the program doing the processing to select the appropriate mode.

Processing of top-level forms in the file compiler works as follows:

- If the form is a macro call, it is expanded and the result is processed as a top-level form in the same processing mode (compile-time-too or not-compile-time).

- If the form is a `progn` (or `locally` (LOCALLY-TOP-LEVEL) ) form, each of its body forms is sequentially processed as top-level forms in the same processing mode.

- If the form is a `compiler-let`, `macrolet`, or `symbol-macrolet`, the file compiler makes the appropriate bindings and recursively processes the body forms as an implicit top-level `progn` with those bindings in effect, in the same processing mode.

- If the form is an `eval-when` form, it is handled according to the following table:

  In the preceding table the column LT asks whether `:load-toplevel` is one of the situations specified in the `eval-when` form; CT similarly refers to `:compile-toplevel` and EX to `:execute`. The column CTTM asks whether the `eval-when` form was encountered while in compile-time-too mode. The phrase ``process body'' means to process the body as an implicit top-level `progn` in the indicated mode, and ``evaluate body'' means to evaluate the body forms sequentially as an implicit `progn` in the dynamic execution context of the compiler and in the lexical environment in which the `eval-when` appears.

- Otherwise, the form is a top-level form that is not one of the special cases. If in compile-time-too mode, the compiler first evaluates the form and then performs normal compiler processing on it. If in not-compile-time mode, only normal compiler processing is performed (see section 25.1). Any subforms are treated as non-top-level forms.

Note that top-level forms are guaranteed to be processed in the order in which they textually appear in the file, and that each top-level form read by the compiler is processed before the next is read. However, the order of processing (including, in particular, macro expansion) of subforms that are not top-level forms is unspecified.

For an `eval-when` form that is not a top-level form in the file compiler (that is, either in the interpreter, in `compile`, or in the file compiler but not at top level), if the `:execute` situation is specified, its body is treated as an implicit `progn`. Otherwise, the body is ignored and the `eval-when` form has the value `nil`.

For the sake of backward compatibility, a situation may also be `compile`, `load`, or `eval`. Within a top-level `eval-when` form these have the same meaning as `:compile-toplevel`, `:load-toplevel`, and `:execute`, respectively; but their effect is undefined when used in an `eval-when` form that is not at top level.

The following effects are logical consequences of the preceding specification:

- It is never the case that the execution of a single `eval-when` expression will execute the body code more than once.

- The old keyword `eval` was a misnomer because execution of the body need not be done by `eval`. For example, when the function definition

           (defun foo () (eval-when (:execute) (print 'foo)))

  is compiled the call to `print` should be compiled, not evaluated at compile time.

- Macros intended for use in top-level forms should arrange for all side-effects to be done by the forms in the macro expansion. The macro-expander itself should not perform the side-effects.

      (defmacro foo ()
        (really-foo)                              ;Wrong
        `(really-foo))

      (defmacro foo ()
        `(eval-when (:compile-toplevel
                     :load-toplevel :execute)     ;Right
          (really-foo)))

  Adherence to this convention will mean that such macros will behave intuitively when called in non-top-level positions.

- Placing a variable binding around an `eval-when` reliably captures the binding because the ``compile-time-too'' mode cannot occur (because the `eval-when` could not be a top-level form). For example,

      (let ((x 3))
        (eval-when (:compile-toplevel :load-toplevel :execute)
          (print x)))

  will print 3 at execution (that is, load) time and will not print anything at compile time. This is important so that expansions of `defun` and `defmacro` can be done in terms of `eval-when` and can correctly capture the lexical environment. For example, an implementation might expand a `defun` form such as

      (defun bar (x) (defun foo () (+ x 3)))

  into

      (progn (eval-when (:compile-toplevel)
               (compiler::notice-function 'bar '(x)))
             (eval-when (:load-toplevel :execute)
               (setf (symbol-function 'bar)
                     #'(lambda (x)
                         (progn (eval-when (:compile-toplevel)
                                  (compiler::notice-function 'foo
                                                             '()))
                                (eval-when (:load-toplevel :execute)
                                  (setf (symbol-function 'foo)
                                        #'(lambda () (+ x 3)))))))))

  which by the preceding rules would be treated the same as

      (progn (eval-when (:compile-toplevel)
               (compiler::notice-function 'bar '(x)))
             (eval-when (:load-toplevel :execute)
               (setf (symbol-function 'bar)
                     #'(lambda (x)
                         (progn (eval-when (:load-toplevel :execute)
                                  (setf (symbol-function 'foo)
                                        #'(lambda () (+ x 3)))))))))

Here are some additional examples.

    (let ((x 1))
      (eval-when (:execute :load-toplevel :compile-toplevel)
        (setf (symbol-function 'foo1) #'(lambda () x))))

The `eval-when` in the preceding expression is not at top level, so only the `:execute` keyword is considered. At compile time, this has no effect. At load time (if the `let` is at top level), or at execution time (if the `let` is embedded in some other form which does not execute until later), this sets `(symbol-function 'foo1)` to a function that returns `1`.

    (eval-when (:execute :load-toplevel :compile-toplevel)
      (let ((x 2))
        (eval-when (:execute :load-toplevel :compile-toplevel)
          (setf (symbol-function 'foo2) #'(lambda () x)))))

If the preceding expression occurs at the top level of a file to be compiled, it has both a compile time and a load-time effect of setting `(symbol-function 'foo2)` to a function that returns `2`.

    (eval-when (:execute :load-toplevel :compile-toplevel)
      (setf (symbol-function 'foo3) #'(lambda () 3)))

If the preceding expression occurs at the top level of a file to be compiled, it has both a compile time and a load-time effect of setting the function cell of `foo3` to a function that returns `3`.

    (eval-when (:compile-toplevel)
      (eval-when (:compile-toplevel)
        (print 'foo4)))

The preceding expression always does nothing; it simply returns `nil`.

    (eval-when (:compile-toplevel)
      (eval-when (:execute)
        (print 'foo5)))

If the preceding form occurs at the top level of a file to be compiled, `foo5` is printed at compile time. If this form occurs in a non-top-level position, nothing is printed at compile time. Regardless of context, nothing is ever printed at load time or execution time.

    (eval-when (:execute :load-toplevel)
      (eval-when (:compile-toplevel)
        (print 'foo6)))

If the preceding form occurs at the top level of a file to be compiled, `foo6` is printed at compile time. If this form occurs in a non-top-level position, nothing is printed at compile time. Regardless of context, nothing is ever printed at load time or execution time.

Next: Predicates Up: Top-Level Forms Previous: Declaring Global Variables