not compiling; the compiler is just another instance of file processing programs. On the other
hand, sometimes the idiom is used to execute code needed by the compiler, as when a function
is defined that is called by a macro later in the file. In the COMMON LISP standard as it exists
today, however, there is no read context for eval-when.
The problem for a code analysis program9
is to determine when to evaluate [implicit] eval-when forms and when to merely analyze them.
For example, if set-macro-character is
called in the body of a function, it should not be evaluated, but what if it were lexically inside a
let in a source file but outside any defun? Should calls to macros that expand into eval-when
forms be evaluated? `
Generally, compilers (and other code analyzers) will resolve the ambiguity by distinguishing
between "top-level" forms and "embedded" forms. Top-level [implicit] eval-when forms are
evaluated at analysis (i.e., compile) time; embedded forms are only processed as code. XREF
takes a common denominator approach: Forms defining named program objects -- functions,
macros, variables -- set up a context in which lexically enclosed forms are embedded; anything
outside is considered top-level.
The top-level forms distinction is important for writers of portable programs, since it concerns
the reader and compiler directives that are part of portable COMMON LISP. Since it is
a source of ambiguity, the following recommendation is in order:
- Portability Tip 2:
- Assume that nothing is evaluated by the compiler unless it is a top-level
form enclosed in eval-when, except for those listed on page 182 of CLtL. Explicitly wrap
(eval-when (compile eval load) form) around any form that needs to be evaluated
before subsequent forms can be processed. Only use eval-when outside of the lexical
contours of function and macro definitions; eval-when in embedded forms is ambiguous
and therefore not portable.
5 Compiler Side-effects
Implicit eval-when forms such as in-package can cause permanent side effects to the environment
in which they are executed. For example, in-package can create a new package or
change its relationship to other packages. Other forms produce side-effects used by the compiler
(or XREF) to process later forms. For instance, macro definitions must be "remembered" by
the compiler so that subsequent forms that call the macros can be properly expanded. Other
"compiler side-effects" include defsetf, defstruct, deftype, and calls to proclaim. Any code
enclosed in (eval-when (compile . . . ) code) can change the state of the environment in which
the compiler executes.
Evaluating arbitrary user code in the current LISP environment can be dangerous, because
it may break existing code by redeiining existing functions and macros, altering the properties
of symbols, or changing the state of the
reader.10
It can also change the behavior of functions
*****************
9
including language-specific editors, which have to know how to process package-manipulating forms.
10
A common mistake made by overzealous novice programmers is to define reader macros and modify the
readtable in the top level of a file; when the compiler processes that file, Lisp's reader is permanently altered,
sometimes beyond repair!
|