「20.6 EVAL-WHEN」に書いてある内容がどう考えてもおかしくて、これは翻訳のミスじゃないかと思って調べてみたら、やはり正誤表に載っていた。とはいえ多分、そもそも原文も分かりにくいのだろうと思う。HyperSpecの説明の方がずっと分かりやすい。
:compile-toplevel と :load-toplevel が意味を持つのは、次の2つの条件が揃ったときだけだ。
- COMPILE-FILE でlispファイルをコンパイルするとき
- EVAL-WHEN がトップレベルフォームとして現れる場合
:comile-toplevel が指定されていれば、コンパイル時に評価される。:load-toplevel が指定されていれば、faslファイルを LOAD したときに評価される。
上の2条件が揃わない場合は、「:execute が指定されていれば評価される」「:execute が指定されていないと評価されない」という、ごく単純な動作になる。
HyperSpecに載っている例よりも、さらに直接的な例を考えてみた。
(eval-when (:execute) (defun foo () "foo-execute")) (eval-when (:compile-toplevel) (defun foo () "foo-compile-toplevel")) (eval-when (:load-toplevel) (defun foo () "foo-load-toplevel")) (defmacro foo-macro() (foo)) (defun main() (format t "~a~%" (foo)) (format t "~a~%" (foo-macro)))
LOAD でlispファイルを読み込めば、
foo-execute foo-execute
と表示される。COMPILE-FILEでコンパイルしたfaslファイルを読み込めば、
foo-load-toplevel foo-compile-toplevel
と表示される。