次: , 前: Expansion, 上: Macros


12.3 マクロとバイトコンパイル

なぜ、マクロの展開形をわざわざ計算してから展開形を評価するのか、 疑問に思うかもしれません。 なぜ、マクロ本体で望みの結果を直接出さないのでしょう? その理由には、コンパイルが関係しています。

コンパイルするLispプログラムにマクロ呼び出しが現れると、 Lispコンパイラは、インタープリタがするのと同様にマクロ定義を呼び出し、 その展開形を受け取ります。 この展開形を評価するかわりに、コンパイラは、 展開形がプログラムに直接現れたかのようにそれをコンパイルします。 その結果、コンパイル済みのコードは、マクロが意図した値と副作用を生じ、 かつ、実行速度はコンパイルした速度になるのです。 マクロ本体そのもので値と副作用を計算したのでは、 このように動作しません。 コンパイル時に計算してしまい、それでは意味がありません。

マクロ呼び出しが正しくコンパイルされるためには、 それらの呼び出しをコンパイルするときに、 Lisp内でマクロが定義済みである必要があります。 コンパイラには、読者がこのようにすることを補佐する機能があります。 コンパイル対象のファイルにフォームdefmacroが含まれていると、 そのファイルの残りをコンパイルするあいだは、 一時的にマクロを定義します。 この機能が動作するためには、 defmacroを同じファイルの最初に利用する箇所よりまえに 入れておく必要があります。

ファイルをバイトコンパイルすると、 そのファイルのトップレベルにあるrequireの呼び出しを実行します。 これは、ファイルを正しくコンパイルするために必要なパッケージを表します。 コンパイル中に必要なマクロ定義が使えることを保証する1つの方法は、 それらのマクロを定義するファイルを requireに指定しておくことです(see Named Features)。 コンパイル済みのプログラムを実行するときに、 マクロを定義したファイルをロードしてしまうことを避けるには、 requireの呼び出しの周りにeval-when-compileを書いておきます (see Eval During Compile)。