如何解释Common Lisp中的逗号 - 逗号?

时间:2013-08-24 12:42:01

标签: lisp common-lisp

修改:在我的示例中,=>表示“评估为”,->表示“展开到macroexpand-1下”。

我正试图围绕Common Lisp中的嵌套式引用进行报道,我认为我非常接近理解它,感谢其他几个SO问题(请不要将我引用给他们 - 我看过他们了。最后一件事就是唠叨我。考虑:

`(a `(b ,,@(list 'c 'd)))

=> (a `(b ,c ,d))

遵循在CLHS中扩展后引用表单的算法,我逐步完成了上面第一个表单的(读取时间)扩展过程,实际上,评估从该扩展中获得的表单确实给出了相同的结果。现在,考虑一下Peter Seibel在他出色的着作中给出的once-only的定义。

(defmacro once-only ((&rest names) &body body)
  (let ((gensyms (loop for n in names collect (gensym))))
    `(let (,@(loop for g in gensyms collect `(,g (gensym))))
      `(let (,,@(loop for g in gensyms for n in names collect ``(,,g ,,n)))
        ,(let (,@(loop for n in names for g in gensyms collect `(,n ,g)))
           ,@body)))))

鉴于该定义,SBCL显示以下宏扩展:

(once-only (from to)
  `(do ((,var ,from (next-prime (+ 1 ,var))))
       ((>= ,var ,to))
     ,@body)))

-> (LET ((#:G939 (GENSYM)) (#:G940 (GENSYM)))
     `(LET ((,#:G939 ,FROM) (,#:G940 ,TO))
       ,(LET ((FROM #:G939) (TO #:G940))
         `(DO ((,VAR ,FROM (NEXT-PRIME (+ ,1 ,VAR)))) ((>= ,VAR ,TO)) ,@BODY))))

现在,我的问题是扩展表单的第二行。不应该是:

`(LET (,(,#:G939 ,FROM) ,(,#:G940 ,TO))

请参阅上面第一个示例中对,,@的评估最终如何将逗号“分发”到从列表(c d)拼接的元素中?为什么不在这里发生?这两个例子似乎共享相同的结构,但他们的评估结果似乎不一致。

1 个答案:

答案 0 :(得分:1)

我想我看到了我的错误。上面宏观扩张的第二行实际上应该是:

`(LET (,`(,#:G939 ,FROM) ,`(,#:G940 ,TO))

这相当于SBCL所示。