Macros
Macro calls are expanded in both body and patterns. This can be very useful to have both make and match macros, but be careful with names.
A macro is function of two argument which is a called with a list of
the arguments to the macro call and the current macro environment. It
can be either a lambda
or a match-lambda
. The basic forms for
defining macros are:
(define-macro name lambda|match-lambda)
(let-macro ((name lambda|match-lambda)
...)
Macros are definitely NOT hygienic in any form.
To simplify writing macros there are a number of predefined macros:
(defmacro name (arg ...) ...)
(defmacro name arg ...)
(defmacro name ((argpat ...) body) ...)
Defmacro can be used for defining simple macros or sequences of matches depending on whether the arguments are a simple list of symbols or can be interpreted as a list of pattern/body pairs. In the second case when the argument is just a symbol it will be bound to the whole argument list. For example:
(defmacro double (a) `(+ ,a ,a))
(defmacro my-list args `(list ,@args))
(defmacro andalso
((list e) `,e)
((cons e es) `(if ,e (andalso ,@es) 'false))
(() `'true))
The macro definitions in a macrolet
obey the same rules as
defmacro
.
The macro functions created by defmacro
and macrolet
automatically add the second argument with the current macro environment
with the name $ENV
. This allows explicit expansion of macros inside
the macro and also manipulation of the macro environment. No changes to
the environment are exported outside the macro.
User defined macros shadow the predefined macros so it is possible to redefine the built-in macro definitions. However, see the caveat below!
Yes, we have the backquote
. It is implemented as a macro so it is
expanded at macro expansion time.
Local functions that are only available at compile time and can be
called by macros are defined using eval-when-compile
:
(defmacro foo (x)
...
(foo-helper m n)
...)
(eval-when-compile
(defun foo-helper (a b)
...)
)
There can be many eval-when-compile
forms. Functions defined within
an eval-when-compile
are mutually recursive but they can only call
other local functions defined in an earlier eval-when-compile
and
macros defined earlier in the file. Functions defined in
eval-when-compile
which are called by macros can be defined after
the macro but must be defined before the macro is used.
Scheme's syntax rules are an easy way to define macros where the body
is just a simple expansion. These are supported with defsyntax
and
syntaxlet
. Note that the patterns are only the arguments to the macro
call and do not contain the macro name. So using them we would get:
(defsyntax andalso
(() 'true)
((e) e)
((e . es) (case e ('true (andalso . es)) ('false 'false))))
NOTE: These are definitely NOT hygienic.
CAVEAT: While it is perfectly legal to define a Core form as a macro these will silently be ignored by the compiler.