これらの機能によりプログラムのコンパイル中に評価されるコードを記述できます。
このフォームはそれを含むコードがコンパイルされるとき、および(コンパイルされているかいないかに関わらず)実行されるときの両方で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”の警告は抑制される)。
このフォームはbodyがコンパイル時に評価され、コンパイルされたプログラムがロードされるときは評価されないようにマークする。コンパイラーによる評価の結果はコンパイル済みのプログラム内の定数となる。ソースファイルをコンパイルではなくロードすると、bodyは通常どおり評価される。
生成するために何らかの計算が必要な定数があるなら、eval-when-compile
はコンパイル時にそれを行なうことができる。たとえば、
(defvar gauss-schoolboy-problem (eval-when-compile (apply #'+ (number-sequence 1 100))))
他のパッケージを使用しているが、そのパッケージのマクロ(バイトコンパイラーはそれらを展開します)だけが必要なら、それらを実行せずにコンパイル用にロードさせるために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
と近いことを行う。