cl: Time of Evaluation

 
 2.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.
 
  -- Macro: cl-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 ‘cl-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 ‘cl-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 ‘cl-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 ‘cl-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:
           (cl-eval-when (compile)           (setq foo1 'bar))
           (cl-eval-when (load)              (setq foo2 'bar))
           (cl-eval-when (compile load)      (setq foo3 'bar))
           (cl-eval-when (eval)              (setq foo4 'bar))
           (cl-eval-when (eval compile)      (setq foo5 'bar))
           (cl-eval-when (eval load)         (setq foo6 'bar))
           (cl-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 ‘cl-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 ‘(cl-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 ‘(cl-eval-when (compile load eval) ...)’.
 
    Emacs includes two special forms related to ‘cl-eval-when’.  See
 (elisp)Eval During Compile.  One of these, ‘eval-when-compile’, is not
 quite equivalent to any ‘cl-eval-when’ construct and is described below.
 
    The other form, ‘(eval-and-compile ...)’, is exactly equivalent to
 ‘(cl-eval-when (compile load eval) ...)’.
 
  -- Macro: 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.
 
  -- Macro: cl-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, ‘cl-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 ‘cl-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: "
                     (cl-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 Oct 31 16:32:28 2012"
                     ", and loaded on: "
                     --temp--))