これらの機能により、プログラムのコンパイル時に評価されるコードを記述できます。
このフォームは、包含するコードをコンパイルする際と、実行する際(コンパイル済みか否かを問わず)の両方で、body が評価されるよう指定します。
bodyを別ファイルに記述し、requireでそのファイルを参照することでも同様の結果が得られます。bodyが大きい場合は、こちらの方法が好ましいです。実質的にrequireは自動的にeval-and-compileとなり、コンパイル時と実行時の両方でパッケージが読み込まれます。
autoload も実質的に eval-and-compile
と同じです。コンパイル時に認識されるため、このような関数を使用しても「定義されていることが不明」という警告は発生しません。
eval-and-compile の用途の多くは、かなり高度なものです。
マクロに結果を生成するためのヘルパー関数があり、そのマクロがローカルおよびパッケージ外の両方で使用される場合は、コンパイル時とその後の実行時の両方でヘルパーを取得できるよう、eval-and-compile を使用する必要があります。
関数がプログラム的に定義されている場合(例えば fset のように)、eval-and-compile
を使用することで、実行時だけでなくコンパイル時にも定義を行うことができ、その結果、それらの関数への呼び出しがチェックされ(「定義されていることが不明」という警告も抑制されます)。
この形式では、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の動作に近いです。