Next: , Previous: , Up: Byte Compilation   [Contents][Index]


16.5 Evaluation During Compilation

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

Special Form: 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”の警告は抑えられます)。

Special Form: 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と近いことを行います。