0

我正在尝试通过Common Lisp:符号计算的简单介绍一书来学习 Common Lisp 。此外,我正在使用 SBCL、Emacs 和 Slime。

在第 14 章,最后一章,作者介绍了宏。在关于编译它的一节中,他提到:

由于宏扩展可以随时发生,因此您不应编写会产生副作用的宏,例如赋值或 i/o。但是宏可以扩展为产生副作用的表达式。

作为说明不良宏的一种方式,他提供了以下示例:

(defmacro bad-announce-macro ()
 (format t "~%Hi mom!"))


(defun say-hi ()
 (bad-announce-macro))

> (compile ’say-hi)
Hi, mom!
SAY-HI

> (say-hi)
NIL

当我尝试在我的环境中模仿相同的内容时,我有不同的输出:


CL-USER> (defmacro bad-announce-macro ()
            (format t "~%Hi mom!"))
BAD-ANNOUNCE-MACRO
CL-USER> (bad-announce-macro)
Hi mom!
NIL
CL-USER> (defun say-hi ()
           (bad-announce-macro))
Hi mom!
SAY-HI
CL-USER> (say-hi)
NIL
CL-USER> (compile (say-hi))
; Evaluation aborted on #<UNDEFINED-FUNCTION NIL {100408C143}>.
CL-USER> (compile 'say-hi)
SAY-HI
NIL
NIL
CL-USER> (compile `say-hi)
SAY-HI
NIL
NIL

如您所见,在编译函数时,Hi mom!缺少该部分。

为什么会这样?这仅仅是因为 Lisp 实现的不同吗?是否有可能实现相同的输出?

我不认为是这样,但我会从书中放一个打印屏幕,以防这与从 pdf 复制并粘贴到 Emacs Slime 的 REPL 中有关。

在此处输入图像描述

4

1 回答 1

4

默认情况下,SBCL 已经编译了 REPL 中的定义。调用compile一个已经编译的函数然后可能什么都不做。

执行表单Hi, mom!时已经打印了该消息。defun请参阅上面的示例。

Touretzky 在他的书中使用了一个不同的实现,它在 REPL 中使用了一个解释器。然后,用户将通过调用 、 或类似方法调用编译compilecompile-file

于 2021-08-21T09:36:43.530 回答