Previous: Argument Lists, Up: Program Structure

### 3.2 Time of Evaluation

Normally, the byte-compiler does not actually execute the forms in a file it compiles. For example, if a file contains `(setq foo t)`, the act of compiling it will not actually set `foo` to `t`. This is true even if the `setq` was a top-level form (i.e., not enclosed in a `defun` or other form). Sometimes, though, you would like to have certain top-level forms evaluated at compile-time. For example, the compiler effectively evaluates `defmacro` forms at compile-time so that later parts of the file can refer to the macros that are defined.

— Special Form: eval-when (situations...) forms...

> This form controls when the body forms are evaluated. The situations list may contain any set of the symbols `compile`, `load`, and `eval` (or their long-winded ANSI equivalents, `:compile-toplevel`, `:load-toplevel`, and `:execute`).

> The `eval-when` form is handled differently depending on whether or not it is being compiled as a top-level form. Specifically, it gets special treatment if it is being compiled by a command such as `byte-compile-file` which compiles files or buffers of code, and it appears either literally at the top level of the file or inside a top-level `progn`.

> For compiled top-level `eval-when`s, the body forms are executed at compile-time if `compile` is in the situations list, and the forms are written out to the file (to be executed at load-time) if `load` is in the situations list.

> For non-compiled-top-level forms, only the `eval` situation is relevant. (This includes forms executed by the interpreter, forms compiled with `byte-compile` rather than `byte-compile-file`, and non-top-level forms.) The `eval-when` acts like a `progn` if `eval` is specified, and like `nil` (ignoring the body forms) if not.

> The rules become more subtle when `eval-when`s are nested; consult Steele (second edition) for the gruesome details (and some gruesome examples).

> Some simple examples:

>               ;; Top-level forms in foo.el:
>               (eval-when (compile)           (setq foo1 'bar))
>               (eval-when (load)              (setq foo2 'bar))
>               (eval-when (compile load)      (setq foo3 'bar))
>               (eval-when (eval)              (setq foo4 'bar))
>               (eval-when (eval compile)      (setq foo5 'bar))
>               (eval-when (eval load)         (setq foo6 'bar))
>               (eval-when (eval compile load) (setq foo7 'bar))

> When `foo.el` is compiled, these variables will be set during the compilation itself:

>               foo1  foo3  foo5  foo7      ; `compile'

> When `foo.elc` is loaded, these variables will be set:

>               foo2  foo3  foo6  foo7      ; `load'

> And if `foo.el` is loaded uncompiled, these variables will be set:

>               foo4  foo5  foo6  foo7      ; `eval'

> If these seven `eval-when`s had been, say, inside a `defun`, then the first three would have been equivalent to `nil` and the last four would have been equivalent to the corresponding `setq`s.

> Note that `(eval-when (load eval) ...)` is equivalent to `(progn ...)` in all contexts. The compiler treats certain top-level forms, like `defmacro` (sort-of) and `require`, as if they were wrapped in `(eval-when (compile load eval) ...)`.

Emacs includes two special forms related to `eval-when`. One of these, `eval-when-compile`, is not quite equivalent to any `eval-when` construct and is described below.

The other form, `(eval-and-compile ...)`, is exactly equivalent to ‘`(eval-when (compile load eval) ...)`’ and so is not itself defined by this package.

— Special Form: eval-when-compile forms...

> The forms are evaluated at compile-time; at execution time, this form acts like a quoted constant of the resulting value. Used at top-level, `eval-when-compile` is just like ‘`eval-when (compile eval)`’. In other contexts, `eval-when-compile` allows code to be evaluated once at compile-time for efficiency or other reasons.

> This form is similar to the ‘`#.`’ syntax of true Common Lisp.

— Special Form: load-time-value form

> The form is evaluated at load-time; at execution time, this form acts like a quoted constant of the resulting value.

> Early Common Lisp had a ‘`#,`’ syntax that was similar to this, but ANSI Common Lisp replaced it with `load-time-value` and gave it more well-defined semantics.

> In a compiled file, `load-time-value` arranges for form to be evaluated when the `.elc` file is loaded and then used as if it were a quoted constant. In code compiled by `byte-compile` rather than `byte-compile-file`, the effect is identical to `eval-when-compile`. In uncompiled code, both `eval-when-compile` and `load-time-value` act exactly like `progn`.

>               (defun report ()
>                 (insert "This function was executed on: "
>                         (current-time-string)
>                         ", compiled on: "
>                         (eval-when-compile (current-time-string))
>                         ;; or '#.(current-time-string) in real Common Lisp
>                         ", and loaded on: "
>                         (load-time-value (current-time-string))))

> Byte-compiled, the above defun will result in the following code (or its compiled equivalent, of course) in the `.elc` file:

>               (setq --temp-- (current-time-string))
>               (defun report ()
>                 (insert "This function was executed on: "
>                         (current-time-string)
>                         ", compiled on: "
>                         '"Wed Jun 23 18:33:43 1993"
>                         ", and loaded on: "
>                         --temp--))