5

我在 Scheme(使用 DrRacket)中获得了一项任务,要求我使用 cons 从组件 1、2、3 和 () 创建列表 ((1 2) 3)

我已经设法达到 ((1 2) . 3) 使用:

(cons (cons '1 (cons '2 '())) '3)

然而,这是同一回事吗?

4

5 回答 5

5

注意:这是从我对Recursive range in Lisp 添加句点的回答中蚕食的? 问题是不同的(所以不是重复的),但是关于如何从 cons 单元构造列表以及如何打印它们的背景说明是相同的。结局有点不同。

Scheme 中的列表要么是空列表(在某些 Lisps 中()也称为),要么是一个 cons 单元格,其(也称为)是列表的一个元素,其(也称为)是列表的其余部分(即,另一个列表),或终止列表的原子。常规的终止符是空列表;被终止的列表被称为“正确的列表”。由任何其他原子终止的列表称为“不适当的列表”。该列表包含元素 1、2、3、4 和 5,并以 . 结尾。您可以通过以下方式构建它nilcarfirstcdrrest()()(1 2 3 4 5)()

(cons 1 (cons 2 (cons 3 (cons 4 (cons 5 ())))))

现在,当系统打印一个 cons 单元格时,一般情况是通过

(car . cdr)

例如,结果(cons 1 2)打印为

(1 . 2)

由于列表是由 cons 单元格构建的,因此您也可以将这种表示法用于列表:

'(1 2 3 4 5)                      ; ==
'(1 . (2 . (3 . (4 . (5 . ())))))

不过,这相当笨拙,所以大多数 lisps(据我所知)都有一个打印 cons 单元格的特殊情况:如果cdr是一个列表(另一个 cons 单元格或()),那么不要打印.,也不要打印周围的括号cdr(否则它会有,因为它是一个列表)。

有了对列表和 cons 单元的这种理解,我们就可以考虑具体情况((1 2) 3)((1 2) . 3). 让我们将这些分解为缺点单元格。

((1 2) 3)                              ; ==
((1 . (2 . ()) . (3 . ()))             ; ==
(cons (cons 1 (cons 2 ()) (cons 3 ()))  
((1 2) . 3)                   ; ==           
((1 . (2 . ())) . 3)          ; ==
(cons (cons 1 (cons 2 ())) 3)

每种情况下的最后几行都是不同的,因此((1 2) 3)也不((1 2) . 3)相同。

于 2013-10-07T15:08:21.780 回答
2

不,正如其他人所提到的,((1 2) 3)与 相同((1 2) 3 . ()),当然您可以使用 (cons '3 '())而不是文字来构建'3

(cons (cons '1 (cons '2 '())) (cons '3 '()))
于 2013-10-07T14:05:03.750 回答
1

不。

的“顶级”元素(A . B)是单个cons单元格:(cons A B). car缺点单元格的是AcdrB。在正确列表中,cdr元素始终()是非空正确列表或其他非空正确列表。

相比之下,(A B)是一个包含两个元素的列表,每个元素都有一个 cons 单元格:(cons A (cons B ()))

于 2013-10-07T11:21:44.493 回答
1

它们是不同的:

(equal? '((1 2) 3) '((1 2) . 3))
=> #f

因为'((1 2) 3)等价于这个:

(cons (cons 1 (cons 2 '())) (cons 3 '()))

'((1 2) . 3)等价于:

(cons (cons 1 (cons 2 '())) 3)

所以你看,它们有不同的cons细胞结构。第一个版本是正确的列表- 意思是:它以空列表结尾'(),而第二个版本以 结尾3,使其成为不正确的列表

于 2013-10-07T14:06:18.733 回答
1

它们不一样。((1 2) 3)是一个'()终止列表,而((1 2) . 3)只是一个“对”。尝试替换 '3(cons '3 '())

于 2013-10-07T13:48:33.497 回答