使用两个反引号和逗号,Common Lisp

时间:2011-09-26 00:21:54

标签: list syntax common-lisp comma

我正在学习常见的口齿不清,我在理解两个反引号和两个逗号的用法时遇到了问题:

``(a ,,(+ 1 2))

我的意思是,我不知道为什么评价为:

`(A ,3)

而不是那样:

`(A 3)

我在解释自己,为了评估表格前面的两个反引号,两个逗号都被“消耗”,所以没有一个逗号应该离开但还有一个。 怎么看?

``(a ,,(+ 1 2))

仅使用列表和'?

2 个答案:

答案 0 :(得分:23)

来自规格

这就是Common Lisp HyperSpec关于嵌套backticks

的说法
  

如果反引号语法是嵌套的,则应首先扩展最里面的反引号形式。这意味着如果连续出现多个逗号,则最左边的一个逗号属于最内层的反引号。

R5RS计划规范还包括有关backticks的详细信息:

  

Quasiquote表单可以嵌套。仅对于与最外面的反引号出现在相同嵌套级别的未加引号的组件进行替换。嵌套水平在每个连续的准曲线内增加一个,并在每个不相等的内部减少一个。

另外请记住,每次评估只会有一个反引号崩溃,就像常规引用一样,它不是递归的。

行动规则

要了解这三个细节如何相互作用,让我们稍微扩展您的示例。这个表达......

``(a ,,(+ 1 2) ,(+ 3 4))

对此进行求值(以SBCL表示法):

`(A ,3 ,(+ 3 4))
  1. 左反引号崩溃,因此(+ 1 2)被匹配的逗号(2 nd 逗号,根据HyperSpec)转义。
  2. 另一方面,(+ 3 4)没有足够的逗号来扩展(这是R5RS提到的)。
  3. 只有一个反引号被折叠,因为反引号不会被递归扩展。
  4. 扩展逗号

    要摆脱其他反击,需要另一个评估级别:

    (eval ``(a ,,(+ 1 2) ,(+ 3 4)))
    

    两个反引号都消失了,我们留下了一个清单:

    (A 3 7)
    

答案 1 :(得分:2)

不,两个逗号都被消耗了。有两个级别的引用和两个级别的逗号。现在有一个级别的引用和一个级别的逗号。事实上,GNU Common Lisp(2.44.1)将您的表达式评估为

(list 'a 3)

这与

完全相同
`(a ,3)

但更明确地“评估”了两个逗号。