在LISP中使用defmacro时出现未绑定变量错误

在LISP中使用defmacro时出现未绑定变量错误,lisp,common-lisp,clisp,Lisp,Common Lisp,Clisp,我尝试在LISP中使用两个表单的宏,它计算两个表单,但总是返回表单2的结果。以下是我正在使用的代码- (defmacro testmac (x body) (prog2 x body)) 使用以下形式执行宏时,它工作正常,并且始终返回第二种形式的5 (testmac (- 10 6) (/ 10 2)) 但是,当我尝试用以下形式执行宏时,它返回错误 (testmac (print a) (print b)) 下面是我得到的错误- debugger invoked on a UNBOUND

我尝试在LISP中使用两个表单的宏,它计算两个表单,但总是返回表单2的结果。以下是我正在使用的代码-

(defmacro testmac (x body) (prog2 x body))
使用以下形式执行宏时,它工作正常,并且始终返回第二种形式的5

(testmac (- 10 6) (/ 10 2))
但是,当我尝试用以下形式执行宏时,它返回错误

(testmac (print a) (print b)) 
下面是我得到的错误-

debugger invoked on a UNBOUND-VARIABLE: The variable B is unbound.
Type HELP for debugger help, or (SB-EXT:EXIT) to exit from SBCL.
restarts (invokable by number or by possibly-abbreviated name):
0: [ABORT] Exit debugger, returning to top level.
(SB-INT:SIMPLE-EVAL-IN-LEXENV B #<NULL-LEXENV>)
对未绑定变量调用的调试器:变量B未绑定。 键入“帮助”以获取调试器帮助,或键入(SB-EXT:EXIT)以退出SBCL。 重新启动(可通过数字或可能的缩写名称调用): 0:[中止]退出调试器,返回顶层。 (SB-INT:SIMPLE-EVAL-IN-LEXENV B#) 为什么会出现此错误?如何使用宏使其正常工作


另外,我不能使用defun需要使用宏来执行(testmac(print a)(print b))

这是因为您的
testmac
宏直接执行
(prog2 x body)

你需要这样写:

(defmacro testmac (x body)
  `(prog2 ,x ,body))
(macroexpand-1 '(testmac (print 42) (print 51)))
反引号后面的表单不会被计算,但是逗号后面的表单会被计算

您可以(而且应该!)像这样测试扩展:

(defmacro testmac (x body)
  `(prog2 ,x ,body))
(macroexpand-1 '(testmac (print 42) (print 51)))
其中:

(PROG2 (PRINT 42) (PRINT 51))
我尝试在LISP中使用两个表单的宏,它计算两个表单,但总是返回表单2的结果

这通常不是一个好主意——尽管可能只是措辞不准确。宏不应该对代码求值——这不是没有充分理由的。通常宏只是转换代码。然后,生成的代码决定要计算的内容

(defmacro testmac (x body) (prog2 x body))

(testmac (- 10 6) (/ 10 2))
所以
x
是列表
(-106)
,body是列表
(/102)

宏返回第二个列表

CL-USER 11 > (macroexpand-1 '(testmac (print a) (print b)))
(PRINT B)
宏返回格式
(打印b)
。然后它被执行

CL-USER 12 > (testmac (print a) (print b))

Error: The variable B is unbound.
如果
B
未定义,您将看到错误


这里没有魔法。

欢迎来到StackOverflow!这是一个结构合理的第一个问题。然而。。。请写“Lisp”,不带大写字母;)@伊尔哈德。当然,谢谢你的建议。非常欢迎!祝你好运,黑客行为愉快。@Rainer@Ealhad,谢谢大家的反馈和建议。根据大家所指出的,我正在执行代码as(testmac(print'a)(print'b)),它返回b,并且没有错误。它解决了我试图解决的原始问题,即使用macro和prog2评估两种形式(@rainer,我理解这是不可取的),并返回第二种形式的结果。我认为这是正确的解决方案,而不是解决办法。谢谢,谢谢你的意见。1.(PROG2(PRINT 42)(PRINT 51))和testmac(PRINT 42和PRINT 51)都正确返回结果。然而,当我试图执行(prog2(print a)(print b))时,它不再工作,并返回错误-调试器在未绑定变量上调用:变量prog2未绑定,这很奇怪。我发现重现此错误的唯一方法是使用
prog2(print a)(print b)
,而不使用外部参数,这是一个很好的失败原因。@MikeRandor只是为了澄清一下,当您用
progn
替换
testmac
时,ei<代码>(progn(print a)(print b)),您没有收到错误?@sylvester,根据雷纳指出的,(progn(print a)(print b))将返回并导致错误,因为progn/prog2正在计算未定义的a和b。我试图通过执行(testmac(print'a)(print'b))来解决这个问题,它工作正常,并打印“b”。