我开始学习Scheme,主要是为了好玩,因为我之前从未使用过函数式语言。我之所以选择Scheme,是因为我想长时间阅读SICP。
无论如何,我目前正在学习列表,在此之前我了解了cons,car和cdr。还有一个例子可以创建一个带有缺点的列表列表,如下所示:
(cons (list 1 2) (list 3 4))
结果列表是((1 2)3 4),这对我没有意义,我希望((1 2)(3 4))成为结果(列表由两个列表组成) )。为什么它表现得那样?我意识到,如果我要使用汽车,我会得到(1 2),而cdr我会得到(3 4)因为cdr总是返回“其余的”,但我不明白为什么列表没有制作两个名单?
答案 0 :(得分:9)
你得到一个列表,(1 2)
作为第一个元素(汽车),(3 4)
作为其余部分(cdr),因为cons的第一个参数是列表的第一个元素,第二个元素是参数是包含剩余项目的列表。
这非常类似于列表的结构:(正确)列表的每个节点都包含一个元素和一个包含所有其他元素的列表。 cons
创建了一个这样的节点。
如果cons
的第二个参数将成为列表的第二个元素,那么如何创建一个包含三个参数的列表?您必须在此时设置cons
变量,它只是list
的另一个名称。
如果要创建列表列表,请使用(list (list 1 2) (list 3 4))
。
答案 1 :(得分:3)
(list (list 1 2)
(list 3 4))
与
相同(cons (list 1 2)
(cons (list 3 4)
'()))
结果是
((1 2) (3 4))
也可以写成
((1 . (2 . ()))
.
((3 . (4 . ()))
.
()))
答案 2 :(得分:1)
list A: [ | ]
1 [ | ]
2 /
list B: [ | ]
3 [ | ]
4 /
======================
(cons A B)
[ | ]
[ | ] [ | ]
1 [ | ] 3 [ | ]
2 / 4 /
内部结构的图形表示可以帮助我们可视化问题。
这将有助于更多:
[ | ]
X [ | ]
3 [ | ]
4 /
你看到了这种模式吗?以上是列表(X 3 4)
。这就是(cons A B)
仅将car
部分作为单独列表而不是cdr
绘制的原因。
答案 3 :(得分:0)
因为cons-cell 不是两个元素的列表,所以这两个元素经常混淆。如果(a . b)
是一个cons单元格,则(a . (b . ()))
是两个元素的列表。任何列表都安全,空列表具体是一个cons单元,其car字段包含第一个元素,其cdr字段包含包含其余元素的列表。因此,列表只是一个二叉树,其最右边的叶子是特殊常量()
或nil
,具体取决于您的方言。
这就是为什么(cons 0 '(1 2 3))
评估为(0 1 2 3)
而非(0 (1 2 3))
的原因我们创建了一个车辆为0
且其cdr为(1 2 3)
的cons小区,因此列表(0 1 2 3)
。