Argument Lists Program Structure Function Aliases
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
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
at compile-time so that later parts of the file can refer to the
macros that are defined.
eval(or their long-winded ANSI equivalents,
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
For compiled top-level
eval-whens, 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
byte-compile rather than
and non-top-level forms.) The
eval-when acts like a
eval is specified, and like
(ignoring the body forms) if not.
The rules become more subtle when
eval-whens 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))
foo.el' is compiled, these variables will be set during
the compilation itself:
foo1 foo3 foo5 foo7 ; `compile'
foo.elc' is loaded, these variables will be set:
foo2 foo3 foo6 foo7 ; `load'
And if `
foo.el' is loaded uncompiled, these variables will
foo4 foo5 foo6 foo7 ; `eval'
If these seven
eval-whens had been, say, inside a
then the first three would have been equivalent to
nil and the
last four would have been equivalent to the corresponding
(eval-when (load eval) ...) is equivalent
(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 19 includes two special forms related to
One of these,
eval-when-compile, is not quite equivalent to
eval-when construct and is described below. This package
defines a version of
eval-when-compile for the benefit of
Emacs 18 users.
The other form,
(eval-and-compile ...), is exactly
equivalent to `
(eval-when (compile load eval) ...)' and
so is not itself defined by this package.
eval-when-compileis just like `
eval-when (compile eval)'. In other contexts,
eval-when-compileallows code to be evaluated once at compile-time for efficiency or other reasons.
This form is similar to the `
#.' syntax of true Common Lisp.
Early Common Lisp had a `
#,' syntax that was similar to
this, but ANSI Common Lisp replaced it with
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
effect is identical to
eval-when-compile. In uncompiled
act exactly like
(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 `
(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--))