- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
必须使用 eval-when
是为了确保宏所依赖的函数在编译和使用宏时可用。但是,我想不出一个例子来说明不使用 eval-when
的后果。 .
(defpackage :eval-when
(:use :cl))
(in-package :eval-when)
(defun util-fun (x) (* x x))
(defmacro needs-help (x) `(let ((a (util-fun ,x))) a))
;; use it in the same file
(defun use-the-macro (x) (needs-help x))
(use-the-macro 5)
(defun util-fun ...)
应该用
eval-when
包裹.
; SLIME 2.19
CL-USER> (uiop:getcwd)
#P"/home/anticrisis/dev/common-lisp/eval-when/"
CL-USER> (compile-file "eval-when.lisp")
; compiling file "/home/anticrisis/dev/common-lisp/eval-when/eval-when.lisp" (written 14 AUG 2017 11:30:49 AM):
; compiling (DEFPACKAGE :EVAL-WHEN ...)
; compiling (IN-PACKAGE :EVAL-WHEN)
; compiling (DEFUN UTIL-FUN ...)
; compiling (DEFMACRO NEEDS-HELP ...)
; compiling (DEFUN USE-THE-MACRO ...)
; compiling (USE-THE-MACRO 5)
; /home/anticrisis/dev/common-lisp/eval-when/eval-when.fasl written
; compilation finished in 0:00:00.009
#P"/home/anticrisis/dev/common-lisp/eval-when/eval-when.fasl"
NIL
NIL
CL-USER> (in-package :eval-when)
#<PACKAGE "EVAL-WHEN">
EVAL-WHEN> (use-the-macro 3)
; Evaluation aborted on #<UNDEFINED-FUNCTION USE-THE-MACRO {10035E1103}>.
EVAL-WHEN> (needs-help 4)
; Evaluation aborted on #<UNDEFINED-FUNCTION UTIL-FUN {100387FE33}>.
EVAL-WHEN> (load "eval-when.lisp")
T
EVAL-WHEN> (use-the-macro 3)
9
EVAL-WHEN> (needs-help 4)
16
EVAL-WHEN>
compile-file
和
load
命令来证明没有发生错误。 (当我在编译之后但在加载之前尝试使用这些函数时,我确实收到了一个错误,但任何卸载的代码都会发生这种情况。)
eval-when
括起来。形式,或加载到单独的文件中。 eval-when
时生成的编译时、加载时或运行时错误的示例将有助于我的理解。
最佳答案
记住
EVAL-WHEN 用于告诉文件编译器它是否应该在编译时执行代码(它通常不会在函数定义中执行)以及是否应该将编译后的代码安排在加载时执行的编译文件中。这仅适用于顶级表单。
Common Lisp 在完整的 Lisp 环境中运行文件编译器(请记住我们谈论的是编译文件,而不是在 REPL 中执行),并且可以在编译时运行任意代码(例如作为开发环境工具的一部分,生成代码,优化代码等)。如果文件编译器想要运行代码,那么文件编译器需要知道定义。
还要记住,在宏扩展期间,宏的代码被执行以生成扩展代码。宏的所有函数和宏本身计算代码的调用需要在编译时可用。不需要在编译时可用的是宏形式扩展到的代码。
这有时会造成混淆,但可以学习,然后使用它并不太难。但这里令人困惑的部分是文件编译器本身是可编程的,可以在编译时运行 Lisp 代码。因此,我们需要理解代码可能在不同情况下运行的概念:在 REPL 中、加载时、编译时、宏扩展期间、运行时等。
还要记住,当你编译一个文件时,你需要加载文件,如果编译器稍后需要调用它的一部分。如果一个函数刚被编译,文件编译器会不是 将代码存储在编译时环境中,而不是在完成文件编译之后。如果需要执行代码,则需要加载编译后的代码-> 或使用EVAL-WHEN -> 见下文。
您的代码
您的代码没有 调用 函数util-fun
在编译时。所以函数做 不是 需要在编译时环境中可用。
一个例子
另一个例子,函数实际被调用的地方,见下文。这是 Lisp 文件中的代码,由 compile-file
编译.
(defun run-at-compile-time ()
(print 'I-am-called-at-compile-time))
(defmacro foo ()
(run-at-compile-time) ; this function is called for its
; side-effect: it prints something
'(print 'I-am-called-at-runtime)) ; this code is returned
(foo) ; we use the macro in our code, the compiler needs to expand it.
foo
喜欢调用函数
run-at-compile-time
, 在同一个文件中定义。由于它在编译时环境中不可用,因此这是一个错误。文件编译器只生成要存储在磁盘上的函数的代码,这样当编译文件被加载时,函数就会被定义。但是它没有定义运行编译器的 Lisp 内部的函数 -> 文件编译器不能调用它。
(eval-when
(:compile-toplevel ; this top-level form will be executed by the file compiler
:load-toplevel ; this top-level form will be executed at load-time
; of the compiled file
:execute) ; executed whenever else
(defun run-at-compile-time ()
(print 'I-am-called-at-compile-time))
)
关于common-lisp - 在Common Lisp中,什么时候需要用到eval-when,又是怎么知道的呢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45665951/
你们能帮帮我吗,这是我们的讲师给我们的教程问题,无论我们尝试了多少,我们实际上似乎都无法破解它。请帮忙 ; perform some type/error checking, ; then ca
在 Common Lisp 中编写、编译和测试一个函数,该函数接受一个列表并计算列表中正整数的总数。必须编译然后执行包含函数的 .lisp 文件。在编译该文件后开始传递它,列出要生成的结果的结果,从而
我是 Lisp 初学者,我很难理解为什么下面的代码会给我一个错误。 (dolist (elem '(mapcar mapcon)) (when (fboundp `
我听说 Lisp 可以让你重新定义语言本身,我也试图研究它,但没有任何地方明确的解释。有人有一个简单的例子吗? 最佳答案 Lisp 用户将 Lisp 称为 可编程编程语言 .用于符号计算 - 用符号计
Closed. This question is off-topic. It is not currently accepting answers. Learn more。 想改进这个问题吗Updat
这些是 cons 参数的不同组合的输出。我刚开始学习 lisp。有人可以帮我理解这些吗? Break 80 [81]> (CONS '(A) 'B) ((A) . B) Break 80 [81]>
这个问题不太可能帮助任何 future 的访问者;它只与一个小的地理区域、一个特定的时间点或一个非常狭窄的情况有关,这些情况并不普遍适用于互联网的全局受众。为了帮助使这个问题更广泛地适用,visit
我想问一下为什么这个功能不起作用... (defun nenum(ls) (cond ((null ls) nil) ((listp car(ls)) (nenum (rest ls)
如果我有一个原子,例如“a4”,我需要能够将 1 添加到“4”部分以使其成为 a5,但是因为它被认为是一个字符串,所以这是不可能的,所以如果我可以拆分 (a4 ) 到 ((a)(4)) 中,然后我可以
我有一个关于动态构建函数(或类似的东西)的问题。在 Java 中,我可以通过编程将一些 Source 写入字符串,编译该字符串并像函数一样执行它多次。 假设我有一些遗传算法来创建最佳代码以获取 n 个
我是 Common Lisp 的新手,正在学习教程,但无法全神贯注 (equal '(reverse (a b)) '(b a))) 返回零。 非常感谢您的协助。 M. 最佳答案 在 lisp 中引
我有一个使用列表表示的树。例如: (1 ((2 (3)) (3 (2)))) (2 ((1 (3)) (3 (1)))) (3 ((1 (2)) (2 (1)))))` 现在我需要在维护层次结构树的同
在此站点:http://www.gigamonkeys.com/book/practical-a-simple-database.html有如下列出的用户入口函数: (defun prompt-rea
我对 lisp 比较陌生,对在以下上下文中使用嵌套列表的最佳方法很好奇: 所以,我有以下功能: (defun get-p0 (points) (loop for (label x y) in
我正在为 CLOS 类编写一个函数,该函数反转所述类对象的列表元素。 我有一个返回反向列表的方法,但如何让它将对象的列表设置为该列表?我可以在存储列表的函数中有一个实例变量,然后将元素设置为那个吗?或
我知道,严格来说,没有编译语言或解释语言这回事。 但是,一般来说,LISP 是用来编写 Python、bash 脚本、批处理脚本之类的脚本的吗? 还是像 C++、JAVA 和 C# 这样的通用编程语言
在此站点 http://jatha.sourceforge.net/快速函数的示例是通过递归。是不是递归通常比 Lisp 中的迭代更快并且性能更好? 编辑:Lisp 是否比其他语言更优化递归? 最佳答
另一个新手(常见)LISP 问题: 基本上在大多数编程语言中,函数都有一种方法接收对变量的引用而不仅仅是值,即通过引用传递而不是通过值传递。比方说,为了简单起见,我想编写一个 LISP 函数来接收一个
这个问题在这里已经有了答案: How do I find the index of an element in a list in Racket? (3 个答案) 关闭 9 年前。 如果我有这样的列
我在为这个程序生成正确的输出时遇到了一些问题。我的输出几乎是正确的,但缺少一些步骤。我的代码如下: (defun kt (x y m n) ;set the
我是一名优秀的程序员,十分优秀!