请给我一点帮助。我正在尝试创建这个lisp宏,它将一个(数字)列表作为输入并返回这些数字的总和。代码
(setf g (list 1 2 3 4))
(defmacro add-test(var)
`(+ ,@var))
(add-test g)
会出现此错误
The value G is not of type LIST.
[Condition of type TYPE-ERROR]
同时(add-test (1 2 3 4))
给出正确的结果,即10。
请解释一下,为什么在将变量传入函数时它不起作用?
其他细节 -
Lispbox - SBCL
Ubuntu Linux
提前致谢
答案 0 :(得分:9)
这很容易,也是最常见的宏观问题之一。
(add-test g)
现在,在宏扩展时,调用宏ADD-TEST
,参数VAR
获取值G
,即符号。
然后尝试列表操作。反引号表达式
`(+ ,@var)
VAR
的值为G
,您尝试将其拼接到列表(+ ... )
中。现在返回的表达式为(+ . G)
。
CL-USER 12 > (macroexpand '(add-test g))
(+ . G)
T
(+ . G)
不是有效的Lisp表单。它不是有效的源代码。
请记住,宏的参数是未评估的源表达式。
将其与以下内容进行比较:
CL-USER 13 > (macroexpand '(add-test (1 2 3 4)))
(+ 1 2 3 4)
T
你说:'你能解释一下,为什么当变量传入函数时它不起作用?'
请记住,ADD-TEST
不是一个函数,它是一个宏。宏获取传递的源代码并返回一个新表单 - 然后对该表单进行评估。