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-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 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--))