评估-何时使用? [英] Eval-when uses?
问题描述
在阅读了很多有关Lisp eval-when
运算符的文档后,我仍然不了解它的用途,我知道使用该运算符可以控制表达式的计算时间,但是我无法弄清楚可能出现的任何示例适用吗?
After reading a lot of documentation regarding Lisp eval-when
operator I still can't understand its uses, I know with this operator I can control the evaluation time of my expressions but I can't figure out any example where this may be applicable ?
最好的问候, utxeee.
Best Regards, utxeee.
推荐答案
Lisp文件的编译
以Lisp文件的编译为例. Lisp编译器处理顶级表单.这些可以是任意的Lisp形式,DEFUN,DEFMACROS,DEFCLASS,函数调用,...
Take for example the compilation of a Lisp file. The Lisp compiler processes the top-level forms. These can be arbitrary Lisp forms, DEFUNs, DEFMACROS, DEFCLASS, function calls,...
文件编译器如何工作的整个故事太复杂了,在这里无法解释,但有几件事:
The whole story how the file compiler works is too complex to explain here, but a few things:
-
文件编译器为
(DEFUN foo () )
格式生成代码.但是它不执行defun形式.因此,已知在编译期间存在函数FOO
,但butFOOˋ的代码在编译期间不可用.编译器为已编译文件生成代码,但不将其保存在内存中.您不能在编译时调用此类函数.
the file compiler generates code for a
(DEFUN foo () )
form. But it does not execute the defun form. Thus during compilation it is known that there is a functionFOO
, but the code of ˋFOOˋ is not available during the compilation. The compiler generates the code for the compiled file, but does not keep it in memory. You can't call such a function at compile time.
对于宏,其工作原理略有不同:(DEFMACRO BAZ ...)
.文件编译器不仅会编译宏并注意该宏在其中,而且还会在编译时使该宏可用.它已加载到编译器 environment 中.
for macros this works slightly different: (DEFMACRO BAZ ...)
. The file compiler will not only compile the macro and note that it is there, but it will also make the macro available at compilation time. It is loaded into the compiler environment.
这样想象一下文件中表格的顺序:
Thus imagine the sequence of forms in a file:
(defmacro baz ...)
(defun foo () (baz ...))
之所以可行,是因为文件编译器知道宏BAZ
,并且当编译FOO
的代码时,它可以扩展宏形式.
This works because the file compiler knows the macro BAZ
and when it compiles the code for FOO
, then it can expand the macro form.
现在让我们看下面的示例:
Now let's look at the following example:
(defun bar (form) ...)
(defmacro baz (form) (bar form))
(defun foo () (baz ...))
以上操作无效.现在,宏BAZ
通过调用功能使用BAR
函数.当编译器尝试编译函数FOO
时,它无法扩展BAZ
宏,因为无法调用BAR
,因为BAR
的代码未加载到编译时环境中.
Above will not work. Now the macro BAZ
uses the function BAR
by calling it. When the compiler tries to compile the function FOO
, it can't expand the BAZ
macro, because BAR
can't be called, because the code of BAR
is not loaded into the compile-time environment.
对此有两种解决方案:
- 编译并使用单独的文件更早地加载
BAR
. - 使用 EVAL-WHEN
- compile and load
BAR
earlier using a separate file. - Use EVAL-WHEN
EVAL-WHEN
的示例:
(eval-when (:compile-toplevel :execute :load-toplevel)
(defun bar (form) ...)
)
(defmacro baz (form) (bar form))
(defun foo () (baz ...))
现在EVAL-WHEN
指示文件编译器在编译期间实际运行DEFUN窗体.这样做的效果是:文件编译器现在在编译时就知道BAR
的定义.因此,当在BAZ
用法的宏扩展过程中文件编译器需要调用BAR
时,即可使用它.
Now the EVAL-WHEN
instructs the file compiler to actually run the DEFUN form during compilation. The effect of this is: the file compiler now knows the definition of BAR
at compile time. Thus it is available later, when the file compiler need to call BAR
during macro expansion of the usage of BAZ
.
一个人只能使用:compile-toplevel
,而在编译文件后将不需要该功能时.如果以后使用它,那么我们需要确保它已加载.
One could use only :compile-toplevel
, when the function would not be needed after the compilation of the file. If it is used later, then we need to make sure that it gets loaded.
因此EVAL-WHEN
允许指定是否应运行特定代码段
So EVAL-WHEN
allows to specify if a particular piece of code should be run
- 文件编译期间
- 在加载文件期间
- 执行期间
EVAL-WHEN
在用户代码中不经常使用.如果您使用它,那么您应该问自己是否真的需要它.
EVAL-WHEN
is not used that often in user code. If you use it, then you should ask yourself if you really need it.
这篇关于评估-何时使用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!