基本的Lisp宏错误

bde*_*dev 3 common-lisp

请帮忙.我正在尝试创建这个lisp宏,它将一个(数字)列表作为输入并返回这些数字的总和.代码

(setf g (list 1 2 3 4))

(defmacro add-test(var)
    `(+ ,@var))
Run Code Online (Sandbox Code Playgroud)

(add-test g) 给出了这个错误

The value G is not of type LIST.
[Condition of type TYPE-ERROR]
Run Code Online (Sandbox Code Playgroud)

同时(add-test (1 2 3 4))给出正确的结果,即10.

你能解释一下,为什么在将变量传入函数时它不起作用?

其他详情 -

Lispbox - SBCL

Ubuntu Linux

提前致谢

Rai*_*wig 9

这很简单,也是最常见的宏观问题之一.

(add-test g)
Run Code Online (Sandbox Code Playgroud)

现在在宏扩展时,ADD-TEST使用参数VAR获取值G(符号)来调用宏.

然后尝试列表操作.反引号表达式

`(+ ,@var)
Run Code Online (Sandbox Code Playgroud)

VARis 的值G,并尝试将其拼接到列表中(+ ... ).现在返回的表达式是(+ . G).

CL-USER 12 > (macroexpand '(add-test g))
(+ . G)
T
Run Code Online (Sandbox Code Playgroud)

(+ . G)不是一个有效的Lisp表单.它不是有效的源代码.

请记住,宏的参数是未评估的源表达式.

将其与以下内容进行比较:

CL-USER 13 > (macroexpand '(add-test (1 2 3 4)))
(+ 1 2 3 4)
T
Run Code Online (Sandbox Code Playgroud)

你说:'你能解释一下,为什么当变量传入函数时它不起作用?'

记住,ADD-TEST不是一个功能,它是一个宏.宏获取传递的源代码并返回一个新表单 - 然后稍后评估该表单.

  • @Paul Nathan:你可以对它进行评估,对它进行评估,对其进行修改,应用它 - 几乎没有限制.另请参阅DEFINE-COMPILER-MACRO,它允许您编写优化. (2认同)