评估-何时使用? [英] Eval-when uses?

查看:71
本文介绍了评估-何时使用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在阅读了很多有关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 function FOO, 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.

对此有两种解决方案:

  1. 编译使用单独的文件更早地加载BAR.
  2. 使用 EVAL-WHEN
  1. compile and load BAR earlier using a separate file.
  2. 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆