假设我定义
(defmacro macro-print (str)
(print "hello"))
Run Code Online (Sandbox Code Playgroud)
并运行
(let ((i 0))
(while (< i 3)
(macro-print i)
(setq i (+ 1 i))))
Run Code Online (Sandbox Code Playgroud)
输出是
"hello"
nil
Run Code Online (Sandbox Code Playgroud)
为什么是这样?
我本来期待看到3hello秒。这是因为,根据手册,while特殊形式首先评估其条件,如果评估结果为非零,则评估其主体中的形式。由于条件适用于 的三个值i,因此我希望对(macro-print i)表单进行 3 次评估。每次展开时,它都应该打印“hello”。然而,解释器似乎(macro-print i)在第一次评估时用它的扩展替换(因为 print 返回传递给它的字符串,它会用“hello”替换它)。为什么会发生这种情况?
我已经知道正确的编写方法macro-print是 return (list 'print ,i),但事实上我无法预测循环的实际行为,这表明我对我想要纠正的 lisp 模型存在误解。