第68页,来自Peter Norvig的人工智能编程范例,我们有以下代码:
test -> (a test)
`(this is ,test) -> (this is (a test))
`(this is ,@test) -> (this is a test)
到目前为止一切顺利。拼接逗号会爆炸外括号。但是这个代码没有在书中解释:
`(this is . ,test) -> (this is a test)
它是如何运作的?引擎盖下发生了什么?
答案 0 :(得分:3)
来自[反引号] [1]的CLHS部分:
`(x1 x2 x3 ... xn . ,form)
可能被解释为(append [ x1] [ x2] [ x3] ... [ xn] form)
其中括号表示如上所述的
xj
转换。
所以
`(this is . ,test)
相当于:
(append '(this) '(is) test)
相当于:
(append '(this is) test)
因此,它会创建一个以this is
开头的列表,尾部是test
的内容。
这与用于创建虚线列表的语法相似:
'(1 2 . 3)
因为3
放在列表中最后CDR
的{{1}}中,而不是将CONS
放在正确的列表中。当你使用反引号时,它会将整个列表放在那个地方,所以它就像:
NIL
与
相同'(this is . (a test))
答案 1 :(得分:2)
要了解发生了什么,我们必须重新审视如何在常见的lisp中实现列表。列表是一系列以nil
值结尾的缺点单元格。
(cons 1 (cons 2 (cons 3 nil))) -> (1 2 3)
当我们在列表的末尾插入点时,我们发信号通知读者我们的最终值不是nil
而是非空列表。由于非空列表只是一系列缺点,我们基本上都在说:"用这个列表的开头继续cons细胞链。 (在我们的示例中,此非空列表为test
,其值为(a test)
。
如果我们的列表没有以nil
结尾,那么读者将始终以点显示这一事实:
(cons 1 (cons 2 3) -> (1 2 . 3)