在阅读了很多关于Lisp eval-when运算符的文档后,我仍然不能理解它的用法,我知道使用这个运算符我可以控制我的表达式的计算时间,但我不能找出任何可能适用的示例?
最好的问候,utxeee。
发布于 2012-05-21 01:07:59
Lisp文件的编译
以Lisp文件的编译为例。Lisp编译器处理顶级表单。这些可以是任意的Lisp表单,DEFUNs,DEFMACROS,DEFCLASS,函数调用,...
文件编译器如何工作的整个故事在这里解释起来太复杂了,但有几件事:
(DEFUN foo () )表单生成代码。但是它不会执行defun表单。因此,在编译期间,已知存在函数FOO,但是ˋFOOˋ的代码在编译期间不可用。编译器为编译后的文件生成代码,但不会将其保存在内存中。你不能在编译时调用这样的函数。对于宏,(DEFMACRO BAZ ...)。文件编译器不仅会编译宏并注意到它在那里,而且还会使宏在编译时可用。它被加载到编译器环境中。因此,想象一下文件中的表单序列:
(defmacro baz ...)
(defun foo () (baz ...))这是因为文件编译器知道宏BAZ,并且当它编译FOO的代码时,它可以展开宏形式。
现在让我们看一下下面的例子:
(defun bar (form) ...)
(defmacro baz (form) (bar form))
(defun foo () (baz ...))以上内容将不起作用。现在,宏BAZ通过调用函数BAR来使用该函数。当编译器试图编译函数FOO时,它不能展开BAZ宏,因为BAR不能被调用,因为BAR的代码没有加载到编译时环境中。
有两种解决方案:
BAR。EVAL-WHEN示例
(eval-when (:compile-toplevel :execute :load-toplevel)
(defun bar (form) ...)
)
(defmacro baz (form) (bar form))
(defun foo () (baz ...))现在,EVAL-WHEN指示文件编译器在编译期间实际运行DEFUN表单。这样做的效果是:文件编译器现在在编译时知道BAR的定义。这样以后,当文件编译器需要在宏展开时调用BAR时,就可以使用BAZ了。
当编译文件后不再需要该函数时,只能使用:compile-toplevel。如果以后使用它,那么我们需要确保它被加载。
因此,EVAL-WHEN允许指定是否应该运行特定的代码段
在用户代码中并不经常使用EVAL-WHEN。如果你使用它,那么你应该问问自己是否真的需要它。
https://stackoverflow.com/questions/10674650
复制相似问题