なぜわざわざマクロにたいする展開形を計算して、その後に展開形を評価する手間をかけるのか、不思議に思うかもしれません。なぜマクロbodyは直接望ましい結果を生成しないのでしょうか? それはコンパイルする必要があるからです。
コンパイルされるLispプログラム内にマクロ呼び出しがあるとき、Lispコンパイラーはインタープリターが行うようにマクロ定義を呼び出して展開形を受け取ります。しかし展開形を評価するかわりに、コンパイラーは展開形が直接プログラム内にあるかのようにコンパイルを行います。結果としてコンパイルされたコードはそのマクロにたいする値と副作用を生成しますが、実行速度は完全にコンパイルされたときと同じになります。もしマクロbody自身が値と副作用を計算したら、このようには機能しません — コンパイル時に計算されることになり、それは有用ではありません。
マクロ呼び出しのコンパイルが機能するためには、マクロを呼び出すコードがコンパイルされるとき、そのマクロがLisp内ですでに定義されていなければなりません。コンパイラーにはこれを行うのを助ける特別な機能があります。コンパイルされるファイルがdefmacro
フォームを含むなら、そのファイルの残りの部分をコンパイルするためにそのマクロが一時的に定義されます。
ファイルをバイトコンパイルすると、ファイル内のトップレベルにあるすべてのrequire
呼び出しも実行されるので、それらを定義しているファイルをrequireすることにより、コンパイルの間に必要なマクロ定義が利用できることが確実になります(名前つき機能を参照)。誰かがコンパイルされたプログラムを実行するときに、マクロ定義ファイルのロードをしないようにするには、require
呼び出しの周囲にeval-when-compile
を記述します(コンパイル中の評価を参照)。