GNU Emacs 32.0.50 (9008bf64c3) のマニュアルを PLaMo 翻訳で機械翻訳したものです。誤訳を含むことがあります。原文: https://www.gnu.org/software/emacs/manual/html_node/elisp/Eval-During-Compile.html ・ emacs-doc.conao3.com

17.4 コンパイル時の評価

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

マクロ: eval-and-compile body…

このフォームは、包含するコードをコンパイルする際と、実行する際(コンパイル済みか否かを問わず)の両方で、body が評価されるよう指定します。

bodyを別ファイルに記述し、requireでそのファイルを参照することでも同様の結果が得られます。bodyが大きい場合は、こちらの方法が好ましいです。実質的にrequireは自動的にeval-and-compileとなり、コンパイル時と実行時の両方でパッケージが読み込まれます。

autoload も実質的に eval-and-compile と同じです。コンパイル時に認識されるため、このような関数を使用しても「定義されていることが不明」という警告は発生しません。

eval-and-compile の用途の多くは、かなり高度なものです。

マクロに結果を生成するためのヘルパー関数があり、そのマクロがローカルおよびパッケージ外の両方で使用される場合は、コンパイル時とその後の実行時の両方でヘルパーを取得できるよう、eval-and-compile を使用する必要があります。

関数がプログラム的に定義されている場合(例えば fset のように)、eval-and-compile を使用することで、実行時だけでなくコンパイル時にも定義を行うことができ、その結果、それらの関数への呼び出しがチェックされ(「定義されていることが不明」という警告も抑制されます)。

マクロ: eval-when-compile body…

この形式では、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の動作に近いです。