为什么你必须使用null来获得一个正确的方案列表?

时间:2009-11-06 19:32:05

标签: scheme racket

我意识到这是一个完整的n00b问题,但我很好奇,我想我可能会在这里获得比其他任何地方更好的解释。这是一个列表(我正在使用Dr. Scheme)

> (list 1 2 3)
(1 2 3)

我认为这只是糖:

> (cons 1 (cons 2 (cons 3 null)))
(1 2 3)

另一方面,这也做了别的事情:

> (cons 1 (cons 2 3))
(1 2 . 3)

我的问题是,为什么会有所不同?要求列表末尾的空值有什么意义?

4 个答案:

答案 0 :(得分:11)

列表的定义是递归的。

 1. The null list (empty list) is a list
 2. A list is made up of an item cons a list

所以这些是列表:

1. null  => ()  --read as empty list
2. cons 3 null  =>  (3)
3. cons2 (cons 3 null)  => (2, 3) 

您给出的最后一个示例2 3不符合此列表定义,因此它不是列表。这是缺点接受一个项目和一个列表。 3不是清单。

答案 1 :(得分:2)

cons在列表的开头添加一个新元素,所以当你写的时候你正在做什么:

(cons 1 (cons 2 (cons 3 null)))

以递归方式将项添加到不断增长的列表中,从null开始,该()被定义为空列表 (cons 2 3)。当你打电话给{{1}}时,你不是从空列表开始,所以不是通过在其开头附加2来构建列表。

答案 2 :(得分:2)

包括Scheme在内的Lisp是动态类型的,“lisp方式”是在单个数据结构上有许多函数,而不是针对不同任务的不同数据结构。

所以问题是“在列表末尾要求空值有什么意义?”不是一个正确的问题。

cons函数不要求您提供cons个对象或nil作为其第二个参数。如果第二个参数不是cons对象或nil,那么您将获得一对而不是列表,并且运行时不会使用列表表示法打印它,而是使用点。

因此,如果你想构造一个形状像列表的东西,那么给cons一个列表作为它的第二个参数。如果你想构造其他东西,那么给cons别的东西作为第二个参数。

如果您希望数据结构中只包含两个值,那么对很有用。有一对,你不需要在最后标记它的长度,所以它更有效。对列表是键值映射的简单实现; common lisp具有支持此类属性列表作为其标准库的一部分的功能。

所以真正的问题是“为什么你可以使用相同的cons函数构建对和列表?”,答案是“当你只需要一个时,为什么有两个数据结构?”

答案 3 :(得分:0)

cons语句用于分配汽车为obj1且其cdr为obj2的货币对

(cons obj1 obj2)

因此,有必要结束一个带有null的cons语句,以便我们知道我们是列表的末尾。

> (cons 1 (cons 2 3))
(1 2 . 3)

在该示例中,cdr将是一对< 2,3>。其中2是汽车,3是cdr。不一样:

(list 1 2 3)