なぜ、マクロの展開形をわざわざ計算してから展開形を評価するのか、 疑問に思うかもしれません。 なぜ、マクロ本体で望みの結果を直接出さないのでしょう? その理由には、コンパイルが関係しています。
コンパイルするLispプログラムにマクロ呼び出しが現れると、 Lispコンパイラは、インタープリタがするのと同様にマクロ定義を呼び出し、 その展開形を受け取ります。 この展開形を評価するかわりに、コンパイラは、 展開形がプログラムに直接現れたかのようにそれをコンパイルします。 その結果、コンパイル済みのコードは、マクロが意図した値と副作用を生じ、 かつ、実行速度はコンパイルした速度になるのです。 マクロ本体そのもので値と副作用を計算したのでは、 このように動作しません。 コンパイル時に計算してしまい、それでは意味がありません。
マクロ呼び出しが正しくコンパイルされるためには、
それらの呼び出しをコンパイルするときに、
Lisp内でマクロが定義済みである必要があります。
コンパイラには、読者がこのようにすることを補佐する機能があります。
コンパイル対象のファイルにフォームdefmacro
が含まれていると、
そのファイルの残りをコンパイルするあいだは、
一時的にマクロを定義します。
この機能が動作するためには、
defmacro
を同じファイルの最初に利用する箇所よりまえに
入れておく必要があります。
ファイルをバイトコンパイルすると、
そのファイルのトップレベルにあるrequire
の呼び出しを実行します。
これは、ファイルを正しくコンパイルするために必要なパッケージを表します。
コンパイル中に必要なマクロ定義が使えることを保証する1つの方法は、
それらのマクロを定義するファイルを
require
に指定しておくことです(see Named Features)。
コンパイル済みのプログラムを実行するときに、
マクロを定義したファイルをロードしてしまうことを避けるには、
require
の呼び出しの周りにeval-when-compile
を書いておきます
(see Eval During Compile)。