基本的Lisp宏错误

时间:2010-09-20 20:37:11

标签: common-lisp

请给我一点帮助。我正在尝试创建这个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

提前致谢

1 个答案:

答案 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不是一个函数,它是一个宏。宏获取传递的源代码并返回一个新表单 - 然后对该表单进行评估。