EVAL-WHEN: special operator
功能:控制求值時間點。
使用方式 :
(EVAL-WHEN (opt-list) body)
opt-list: 包括 :compile-toplevel ,:load-toplevel, :execute三個選項
body: 任意合法lisp表達式
------------------------------------------------------------------------------------------------------------------------------
1)、compile-toplevel : 在代碼編譯時求值body,加載及運行時看不到body求值結果。
a. 輔助宏的函數,需要此選項
b. 希望在compile時生成一些固定的信息,比如版本,編譯時間等信息時可使用此選項
2)、load-toplevel : 在加載代碼時求值body求值結果
a. 實現此效果的還有另外三種方式:一種爲通過special operator load-time-value;另一種爲通過special operator macrolet都可以達到加載時求值的效果,最後一種爲閉包,閉包更爲通用。例如在記錄程序開始運行時間的三種實現
;;; 始終表現爲加載時的時間點
(defun get-begin-time-1 nil
(load-time-value (get-universal-time)))
;;; 直接加載源碼時表現爲加載時的時間點;compile之後,表現爲編譯時的時間點
(defun get-begin-time-2 nil
(macrolet ((begin-time nil (get-universal-time)))
(begin-time)))
;;; 運行時求值,閉包實現: 始終表現爲加載時的時間點
(let ((begin-time (get-universal-time)))
(defun get-begin-time-3 nil
begin-time))
;;; 加載時求值
(eval-when (:load-toplevel)
(let ((begin-time (get-universal-time)))
(defun get-begin-time-4 nil
begin-time)))
;;;測試
(mapcar #'funcall '(get-begin-time-1 get-begin-time-2 get-begin-time-3 get-begin-time-4))
b. 頂層表達式及progn的子表達式都會在load時求值。
3)、execute : 在代碼執行時求值。此爲大部分情形下的默認方式。
可以與其它兩個選項組合使用,當execute選項時,表示運行時還會求值;而其它兩個選項只在待定的情形下適用。