首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Eval-何时使用?

Eval-何时使用?
EN

Stack Overflow用户
提问于 2012-05-20 23:17:32
回答 1查看 2.3K关注 0票数 15

在阅读了很多关于Lisp eval-when运算符的文档后,我仍然不能理解它的用法,我知道使用这个运算符我可以控制我的表达式的计算时间,但我不能找出任何可能适用的示例?

最好的问候,utxeee。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2012-05-21 01:07:59

Lisp文件的编译

以Lisp文件的编译为例。Lisp编译器处理顶级表单。这些可以是任意的Lisp表单,DEFUNs,DEFMACROS,DEFCLASS,函数调用,...

文件编译器如何工作的整个故事在这里解释起来太复杂了,但有几件事:

  • 文件编译器为(DEFUN foo () )表单生成代码。但是它不会执行defun表单。因此,在编译期间,已知存在函数FOO,但是ˋFOOˋ的代码在编译期间不可用。编译器为编译后的文件生成代码,但不会将其保存在内存中。你不能在编译时调用这样的函数。对于宏,
  • 的工作原理略有不同:(DEFMACRO BAZ ...)。文件编译器不仅会编译宏并注意到它在那里,而且还会使宏在编译时可用。它被加载到编译器环境中。

因此,想象一下文件中的表单序列:

代码语言:javascript
复制
(defmacro baz ...)

(defun foo () (baz ...))

这是因为文件编译器知道宏BAZ,并且当它编译FOO的代码时,它可以展开宏形式。

现在让我们看一下下面的例子:

代码语言:javascript
复制
(defun bar (form) ...)

(defmacro baz (form) (bar form))

(defun foo () (baz ...))

以上内容将不起作用。现在,宏BAZ通过调用函数BAR来使用该函数。当编译器试图编译函数FOO时,它不能展开BAZ宏,因为BAR不能被调用,因为BAR的代码没有加载到编译时环境中。

有两种解决方案:

  1. 使用单独的文件编译和 load BAR
  2. 使用file

EVAL-WHEN示例

代码语言:javascript
复制
 (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允许指定是否应该运行特定的代码段

  • during of a file
  • during of a file
  • during execution

在用户代码中并不经常使用EVAL-WHEN。如果你使用它,那么你应该问问自己是否真的需要它。

票数 28
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/10674650

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档