我正在尝试通过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 中有关。