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

Paw*_*tko 18 syntax list common-lisp comma

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

``(a ,,(+ 1 2))
Run Code Online (Sandbox Code Playgroud)

我的意思是,我不知道为什么它被评估为:

`(A ,3)
Run Code Online (Sandbox Code Playgroud)

而不是像这样的东西:

`(A 3)
Run Code Online (Sandbox Code Playgroud)

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

``(a ,,(+ 1 2))
Run Code Online (Sandbox Code Playgroud)

仅使用列表和'?

Dan*_*ile 25

从规格

这就是Common Lisp HyperSpec关于嵌套反引号的内容:

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

R5RS Scheme规范还包括有关反引号的这些详细信息:

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

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

行动规则

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

``(a ,,(+ 1 2) ,(+ 3 4))
Run Code Online (Sandbox Code Playgroud)

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

`(A ,3 ,(+ 3 4))
Run Code Online (Sandbox Code Playgroud)
  1. 左反引号崩溃了,所以它(+ 1 2)被匹配的逗号(第二个逗号,根据HyperSpec)转义.
  2. 另一方面,(+ 3 4)没有足够的逗号来扩展(这是R5RS提到的).
  3. 只有一个反引号被折叠,因为反引号不会被递归扩展.

扩展两个逗号

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

(eval ``(a ,,(+ 1 2) ,(+ 3 4)))
Run Code Online (Sandbox Code Playgroud)

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

(A 3 7)
Run Code Online (Sandbox Code Playgroud)