defmacro はマクロを定義する。全ての引数は評価されない。
defmacro で定義された関数では、その関数への全ての引数はリストとしてま とめられ、gvars に束縛される。例えば以下の定義を見てみよう。
(defmacro spread-value x (if (not (null (cdr x))) (cons 'let (cons (list (list 'spread-tmp-val (car x))) (make-setq-form (cdr x)) ))) ) (defun make-setq-form (l) (if (null l) nil (cons (list 'setq (car l) 'spread-tmp-val) (make-setq-form (cdr l))) ))
マクロ関数 spread-value への引数はリストにまとめられ x に束縛される。 例えば、
(spread-value 5680 iroha canna)
と言う呼び出しの場合は (5680 iroha canna) が x に束縛される。
さて上記の定義で、make-setq-form は引数に与えられた物に対して spread-tmp-val を setq する式を作成する。
-> (make-setq-form '(a b)) ((setq a spread-tmp-val) (setq b spread-tmp-val))
マクロ spread-value の本体は変数リストの各変数に対して x の car 部にあ る引数を let 式を組み合わせて代入する lisp 式を生成する。
例えば、x が (0 a b) であるならば、defmacro で与えた本体は以下の式を生 成する(ここでは見やすさのためプリティプリントしている)。
(let ((spread-tmp-val 0)) (setq a spread-tmp-val) (setq b spread-tmp-val) )
マクロ式では、 defmacro で与えられた本体により得られる式をもう一度評価 する。上の例で spread-value を以下のように呼び出した場合、
-> (spread-value 5680 iroha canna)
は、あたかも、
-> (let ((spread-tmp-val 5680)) (setq iroha spread-tmp-val) (setq canna spread-tmp-val) )
を実行したかのように評価が行われ、変数 iroha および canna には 5680 が 束縛される。
ここで、spread-value の第一引数だけは評価が行われ、その他の引数は全く 評価されないことに注意されたい。
このようにマクロはスペシャル型の関数のように、一部引数が評価されない関 数を作成するのに用いられる。
なお、Common Lisp などには defmacro を助ける記法としてバッククオート マクロ(lisp reader により処理されるマクロ記述)を用いることができるが、 canlisp ではバッククオートマクロはサポートしていない。