Common lisp 使用时的附加符号列表@

Common lisp 使用时的附加符号列表@,common-lisp,metaprogramming,sbcl,Common Lisp,Metaprogramming,Sbcl,我观察到一个我不完全理解的宏观扩展: (defmacro test (cons-list) `(list ,@(mapcar #'(lambda(elem) elem) cons-list))) (defmacro test-2 () `(list ,@(list (cons "a" "b")))) (defmacro test-3 (cons-list) `(list ,@cons-list)) 我希望

我观察到一个我不完全理解的宏观扩展:

(defmacro test (cons-list)
  `(list
     ,@(mapcar #'(lambda(elem)
                   elem)
           cons-list)))


(defmacro test-2 ()
  `(list ,@(list (cons "a" "b"))))


(defmacro test-3 (cons-list)
  `(list ,@cons-list))
我希望两个宏以相同的方式展开,因为我只是以一种奇特的方式使用mapcar,再次创建相同的列表,然后使用该列表。 但在SBCL中观察到的结果是:

  • (测试(列表(cons“a”和“b”))
    扩展到
    (列表(cons“a”和“b”)
  • (test-2)
    扩展到
    (列表(“a”“b”))
  • (test-3(列表(cons“a”“b”))
    再次扩展到
    (列表(cons“a”“b”)

为什么这些宏扩展的行为不一样?

Test-2
评估表单
(列表(cons“a”和“b”)
,其他两个没有

记住:宏的参数是读取的、未计算的形式

为了从
test-2
中获得相同的行为,您必须引用以下表格:
,@'(列表(cons“a”“b”)

编辑:这里是
测试的逐步扩展:

`(list
  ,@(mapcar #'(lambda (elem)
                elem)
            cons-list))
删除反引号:

(list* 'list (mapcar #'(lambda (elem)
                         elem)
                     cons-list)
示例中的参数替换:

(list* 'list (mapcar #'(lambda (elem)
                         elem)
                     '(list (cons "a" "b")))
评估
mapcar
表格:

(list* 'list '(list (cons "a" "b")))
评估“列表*”表格:

'(list list (cons "a" "b"))

有道理,但是为什么要增加列表呢?你看到的只是你放进去的东西。不完全是。我希望@会扩展包含cons的列表。因此,在宏Expension的末尾再次出现一个包含cons的列表,您不明白答案。实际上,您正在为宏提供额外的
列表
,这是您不希望看到的。尝试使用
(测试(“a”“b”)
(测试-3(“a”“b”))
。请再次记住,宏参数不是经过计算的,它们是您提供的形式。