common-lisp macros

Help us to keep this website almost Ad Free! It takes only 10 seconds of your time:
> Step 1: Go view our video on YouTube: EF Core Bulk Extensions
> Step 2: And Like the video. BONUS: You can also share it!

Remarks

The Purpose of Macros

Macros are intended for generating code, transforming code and providing new notations. These new notations can be more suited to better express the program, for example by providing domain-level constructs or entire new embedded languages.

Macros can make source code more self-explanatory, but debugging can be made more difficult. As a rule of thumb, one should not use macros when a regular function will do. When you do use them, avoid the usual pitfalls, try to stick to the commonly used patterns and naming conventions.

Macroexpansion Order

Compared to functions, macros are expanded in a reverse order; outmost first, inmost last. This means that by default one cannot use an inner macro to generate syntax required for an outer macro.

Evaluation Order

Sometimes macros need to move user-supplied forms around. One must make sure not to change the order in which they are evaluated. The user may be relying on side effects happening in order.

Evaluate Once Only

The expansion of a macro often needs to use the value of the same user-supplied form more than once. It is possible that the form happens to have side-effects, or it might be calling an expensive function. Thus the macro must make sure to only evaluate such forms once. Usually this will be done by assigning the value to a local variable (whose name is GENSYMed).

Functions used by Macros, using EVAL-WHEN

Complex macros often have parts of their logic implemented in separate functions. One must remember, however, that macros are expanded before the actual code is compiled. When compiling a file, then by default, functions and variables defined in the same file will not be available during macro execution. All function and variable definitions, in the same file, used by a macro must be wrapped inside an EVAL-WHEN-form. The EVAL-WHEN should have all three times specified, when the enclosed code also should be evaluated during load and runtime.

(eval-when (:compile-toplevel :load-toplevel :execute)
  (defun foobar () ...))

This does not apply to functions called from the expansion of the macro, only the ones called by the macro itself.



Got any common-lisp Question?