【问题标题】:Basic Lisp Macro error基本 Lisp 宏错误
【发布时间】:2010-09-20 20:37:10
【问题描述】:

请在这里帮忙。我正在尝试创建这个 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

提前致谢

【问题讨论】:

    标签: common-lisp


    【解决方案1】:

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

    (add-test g)
    

    现在在宏展开时,使用参数VAR 调用宏ADD-TEST,得到值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 不是函数,而是宏。宏获取传递的源代码并返回一个新表单 - 然后对该表单进行评估。

    【讨论】:

    • 感谢 Rainer 的详细回答。这帮助很大。
    • 出于好奇,假设我们将 bdev 的想法更进一步。假设我有某种可优化的表达式(整数列表!),并且我想在“运行时”之前优化表达式。我该怎么做? (虽然我认为 (eval G) 可能会工作......)。
    • @Paul Nathan:你可以评估它、编译它、调用它、应用它——几乎没有限制。另请参阅 DEFINE-COMPILER-MACRO,它允许您编写优化。
    • @Rainer - 我终于找到了解决方案 - (defmacro add-test(x) `(+,@(evalx))) 再次感谢您的解释。
    • @Paul - 感谢“评估”提示。
    猜你喜欢
    • 1970-01-01
    • 2021-08-28
    • 1970-01-01
    • 1970-01-01
    • 2015-06-30
    • 2012-07-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多