我正在学习普通的 lisp,但在理解两个反引号和两个逗号的用法时遇到了问题:
``(a ,,(+ 1 2))
我的意思是,我不知道为什么它被评估为:
`(A ,3)
而不是这样的:
`(A 3)
我在解释自己,两个逗号都被“消耗”了,以便评估表单前面的两个反引号,所以没有一个逗号应该离开,但仍然有一个。看起来如何
``(a ,,(+ 1 2))
仅使用 list 和 ' ?
我正在学习普通的 lisp,但在理解两个反引号和两个逗号的用法时遇到了问题:
``(a ,,(+ 1 2))
我的意思是,我不知道为什么它被评估为:
`(A ,3)
而不是这样的:
`(A 3)
我在解释自己,两个逗号都被“消耗”了,以便评估表单前面的两个反引号,所以没有一个逗号应该离开,但仍然有一个。看起来如何
``(a ,,(+ 1 2))
仅使用 list 和 ' ?
This is what the Common Lisp HyperSpec says about nested backticks:
If the backquote syntax is nested, the innermost backquoted form should be expanded first. This means that if several commas occur in a row, the leftmost one belongs to the innermost backquote.
The R5RS Scheme spec also includes these details about backticks:
Quasiquote forms may be nested. Substitutions are made only for unquoted components appearing at the same nesting level as the outermost backquote. The nesting level increases by one inside each successive quasiquotation, and decreases by one inside each unquotation.
Also keep in mind that only one backtick gets collapsed per evaluation, just like a regular quote, it's not recursive.
To see how these three details interact, let's expand your example a bit. This expression...
``(a ,,(+ 1 2) ,(+ 3 4))
Gets evaluated to this (in SBCL notation):
`(A ,3 ,(+ 3 4))
(+ 1 2)
got escaped by the matching comma (the 2nd comma, according to the HyperSpec).(+ 3 4)
didn't have enough commas to get expanded (which is what R5RS mentions).To get rid of the other backtick, another level of evaluation is needed:
(eval ``(a ,,(+ 1 2) ,(+ 3 4)))
Both backticks are gone, and we're left with a plain list:
(A 3 7)
不,两个逗号都被消耗了。有两级引用和两级逗号。现在有一级引号和一级逗号。事实上,GNU Common Lisp (2.44.1) 将您的表达式计算为
(list 'a 3)
这与
`(a ,3)
但更明确地“评估”了两个逗号。