我正在学习common lisp,但是我不理解两个反引号和两个逗号一起使用的用法:
``(a ,,(+ 1 2))
我的意思是,我不知道为什么它会被评估为:
`(A ,3)
不是像那样的东西:
`(A 3)
我自己解释,两个逗号都被用于评估表单前面的两个反引号,所以没有逗号应该留下,但是仍然有一个逗号。这个逗号是什么意思?
``(a ,,(+ 1 2))
仅使用列表和“?”
我正在学习common lisp,但是我不理解两个反引号和两个逗号一起使用的用法:
``(a ,,(+ 1 2))
我的意思是,我不知道为什么它会被评估为:
`(A ,3)
不是像那样的东西:
`(A 3)
我自己解释,两个逗号都被用于评估表单前面的两个反引号,所以没有逗号应该留下,但是仍然有一个逗号。这个逗号是什么意思?
``(a ,,(+ 1 2))
仅使用列表和“?”
这是 Common Lisp HyperSpec 关于嵌套的 反引号 的说明:
如果反引号语法被嵌套,则应首先展开最内层的反引号形式。这意味着如果有多个逗号连续出现,则最左边的逗号属于最内层的反引号。
R5RS Scheme 规范也包括了关于 反引号 的详细信息:
准引用表单可以嵌套。只有在与最外层反引号处于相同的嵌套级别上的未引用成分才进行替换。嵌套级别在每个连续的准引用中增加一次,在每个取消引用中减少一次。
还要记住,每次评估只会折叠一个反引号,就像常规引号一样,它不是递归的。
为了看到这三个细节如何相互作用,让我们扩展一下你的例子。这个表达式...
``(a ,,(+ 1 2) ,(+ 3 4))
转换成SBCL表示的结果如下:
`(A ,3 ,(+ 3 4))
(+ 1 2)
被第二个逗号(根据HyperSpec)匹配而转义。(+ 3 4)
没有足够的逗号可以扩展(这是R5RS提到的内容)。为了去掉另一个反引号,需要进行另一层求值:
(eval ``(a ,,(+ 1 2) ,(+ 3 4)))
两个反引号都被删除了,最后我们只剩下一个普通列表:
(A 3 7)
不,两个逗号都被使用了。有两个引用级别和两个逗号级别。现在只剩下一个引用级别和一个逗号级别。实际上,GNU Common Lisp (2.44.1)将您的表达式评估为
(list 'a 3)
这与...完全相同。
`(a ,3)
但更明确的是“评估”了两个逗号。