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.