eval-when

Title
eval-when
Type
Special Form
Arguments
eval-when ({SITUATION}*) {FORM}*
Package
lisp
Section
評価
File
builtin.l
ひとことで言うと、フォームをいつ評価するかってことです。

今回の例だと、define-dll-entry などのマクロはコンパイル時に展開
されなければならないのですが、define-dll-entry は foreign で定
義されているので、foreign がロードされていないとマクロであるこ
とが認識できません。(eval-when ...) がなく、単に (require 
"foreign") だけだと、コンパイル時には単なる関数コールだとみなさ
れてしまうため、マクロが展開されなくなってしまいます。そのため
に、eval-when でコンパイルするときも foreign をロードしろと指定
しているわけです。


          ソース                       ソース(左と同一)
            ↓  (eval)                   ↓  (compile)
      Lispインタープリタ           Lispコンパイラ
                                         ↓
                                        *.lc
                                         ↓   (load)
                                   Lispインタープリタ

C言語だと maxというのがマクロですよね。

#define max(a,b)   ((a>b)?a:b)

こんなん。

int foo(int x, int y)
{
   return max(x, y);
}
と書いたら、
int foo(int x, int y)
{
   return ((x> y) ? x : y);
}

こう書いたのと等価ですよね。
Cの入門書だとプリプロセッサがいったん展開してから、コンパイル
すると書かれていると思います。

lispだとこんなんになるんですが

----    test.l ---------

(defmacro macro-max (a b)
  `(if (> ,a ,b) ,a ,b))

(defun foo (x y)
  (macro-max x y))

------------------------

M-x byte-compile-fileってやったときに、
(defmacro macro-maxっていう文は、コンパイルするんでなくって
eval(インタープリタが評価する)しとかないといけない。

でないとfooのところで、コンパイル前にソースを展開できない。

だから eval-when (compile)なんです。
よくわからなかったら、3つ全部つけておけば大丈夫という説もある^^;

(eval-when (:compile-toplevel :load-toplevel :execute)

Common Lispの仕様書では、たしか eval, load, compile
だけ,だったと思います。

eval        --- インタープリタにロードするときeval
compile     --- compile時にeval
load        --- compileした*.lc をロードするときeval

(eval-when (:compile-toplevel :load-toplevel :execute)
って、今まで、xyzzyオリジナルかと思ってました。

でもallegloのhelpをみていたら、
(eval-when (:compile-toplevel :load-toplevel :execute)
ってありますね。^^;
知りませんでした。

| Common Lispの仕様書では、たしか eval, load, compile
| だけ,だったと思います。

CLtL1 ではそうだったんですが、CLtL2 で変わりました。