这些是cons参数的不同组合的输出。我刚开始学口齿不清。有人能帮我理解这些吗?
Break 80 [81]> (CONS '(A) 'B)
((A) . B)
Break 80 [81]> (CONS '(A) '(B))
((A) B)
Break 80 [81]> (CONS 'A 'B)
(A . B)
Break 80 [81]> (CONS 'A '(B))
(A B)
Break 80 [81]>
cons函数总是做同样的事情:它生成一个参数的cons单元格。cons单元格只是一对。您可以使用car获取对的第一个元素,使用cdr获得第二个元素。
对于编写文本单元格,您可以引用并使用(x.y)表示法,其中x是汽车,y则是cdr。使用这个符号,你可以把你的例子写如下(但不要只相信我的话,在REPL中试试):
> '((A) . B ) ;=> ((A) . B)
> '((A) . (B)) ;=> ((A) B)
> '( A . B ) ;=> (A . B)
> '( A . (B)) ;=> (A B)
但是为什么第二种和第四种情况的结果不以我们写它们的方式打印呢?对于cons单元格有特殊的打印约定,因为我们使用cons单元格来实现链表。
有关详细信息,请阅读14.1.2 Conses as Lists,但列表是一个cons单元格,其car是列表的第一个元素,其cdr是列表的其余部分(即另一个列表)。这意味着列表(1 2 3)与(使用文字点对表示法)[1.(2.(3.nil))]相同。你可以在REPL:中尝试
> '(1 . (2 . (3 . nil))) ;=> (1 2 3)
对于列表如此基础的语言来说,这是一个非常有用的打印(和输入)约定。我在回答其他问题时也写了更多关于这一点的文章:
- 方案中的点符号
- Lisp中的递归范围添加句点