Next: , Previous: , Up: バイトコンパイル   [Contents][Index]


17.5 コンパイル中の評価

これらの機能によりプログラムのコンパイル中に評価されるコードを記述できます。

Macro: eval-and-compile body…

このフォームはそれを含むコードがコンパイルされるとき、および(コンパイルされているかいないかに関わらず)実行されるときの両方でbodyが評価されるようにマークする。

bodyを別のファイルに配置して、そのファイルをrequireで参照すれば同様の結果が得られる。これはbodyが大きいときに望ましい方法である。事実上、requireは自動的にeval-and-compileされて、そのパッケージはコンパイル時と実行時の両方でロードされる。

autoloadも実際はeval-and-compileされる。これはコンパイル時に認識されるので、そのような関数の使用により警告“not known to be defined”は生成されない。

ほとんどのeval-and-compileの使用は、完全に妥当であると言えよう。

あるマクロがマクロの結果を構築するためのヘルパー関数をもち、そのマクロがそのパッケージにたいしてローカルと外部の両方で使用される場合には、コンパイル時と後の実行時にそのヘルパー関数を取得するためにeval-and-compileを使用すること。

これは関数がプログラム的に(fsetで)定義されている場合には、コンパイル時と実行時にプログラム的な定義を行わせてそれらの関数の呼び出しをチェックするためにも使用できる(“not known to be defined”の警告は抑制される)。

Macro: eval-when-compile body…

このフォームはbodyがコンパイル時に評価され、コンパイルされたプログラムがロードされるときは評価されないようにマークする。コンパイラーによる評価の結果はコンパイル済みのプログラム内の定数となる。ソースファイルをコンパイルではなくロードすると、bodyは通常どおり評価される。

生成するために何らかの計算が必要な定数があるなら、eval-when-compileはコンパイル時にそれを行なうことができる。たとえば、

(defvar my-regexp
  (eval-when-compile (regexp-opt '("aaa" "aba" "abb"))))

他のパッケージを使用しているが、そのパッケージのマクロ(バイトコンパイラーはそれらを展開します)だけが必要なら、それらを実行せずにコンパイル用にロードさせるためにeval-when-compileを使用できる。たとえば、

(eval-when-compile
  (require 'my-macro-package))

これらの事項は、マクロとdefsubst関数がローカルに定義されていて、そのファイル内だけで使用されることを要求する。これらはそのファイルのコンパイルに必要だが、コンパイル済みファイルの実行には、ほとんどの場合必要ない。たとえば、

(eval-when-compile
  (unless (fboundp 'some-new-thing)
    (defmacro some-new-thing ()
      (compatibility code))))

これは大抵は他のバージョンのEmacsとの互換性の保証のためのコードにたいしてのみ有用である。

Common Lispに関する注意: トップレベルでは、eval-when-compileはCommon Lispのイディオム(eval-when (compile eval) …)に類似する。トップレベル以外では、Common Lispのリーダーマクロ‘#.’(ただし解釈時を除く)が、eval-when-compileと近いことを行う。