compilationmacroslispcommon-lispeval-when

Eval-when uses?


After reading a lot of documentation regarding Lisp eval-when operator I still can't understand its uses, I know with this operator I can control the evaluation time of my expressions but I can't figure out any example where this may be applicable ?

Best Regards, utxeee.


Solution

  • Compilation of a Lisp file

    Take for example the compilation of a Lisp file. The Lisp compiler processes the top-level forms. These can be arbitrary Lisp forms, DEFUNs, DEFMACROS, DEFCLASS, function calls,...

    The whole story how the file compiler works is too complex to explain here, but a few things:

    Thus imagine the sequence of forms in a file:

    (defmacro baz ...)
    
    (defun foo () (baz ...))
    

    This works because the file compiler knows the macro BAZ and when it compiles the code for FOO, then it can expand the macro form.

    Now let's look at the following example:

    (defun bar (form) ...)
    
    (defmacro baz (form) (bar form))
    
    (defun foo () (baz ...))
    

    Above will not work. Now the macro BAZ uses the function BAR by calling it. When the compiler tries to compile the function FOO, it can't expand the BAZ macro, because BAR can't be called, because the code of BAR is not loaded into the compile-time environment.

    There are two solutions to this:

    1. compile and load BAR earlier using a separate file.
    2. Use EVAL-WHEN

    Example for EVAL-WHEN:

     (eval-when (:compile-toplevel :execute :load-toplevel)
       (defun bar (form) ...)
     )
    
     (defmacro baz (form) (bar form))
    
     (defun foo () (baz ...))
    

    Now the EVAL-WHEN instructs the file compiler to actually run the DEFUN form during compilation. The effect of this is: the file compiler now knows the definition of BAR at compile time. Thus it is available later, when the file compiler need to call BAR during macro expansion of the usage of BAZ.

    One could use only :compile-toplevel, when the function would not be needed after the compilation of the file. If it is used later, then we need to make sure that it gets loaded.

    So EVAL-WHEN allows to specify if a particular piece of code should be run

    EVAL-WHEN is not used that often in user code. If you use it, then you should ask yourself if you really need it.