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 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.
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-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
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-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))
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-whens 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 setqs.
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 19 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. 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-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.
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--))