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选项时,表示运行时还会求值;而其它两个选项只在待定的情形下适用。