我意识到这是一个完整的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)
我的问题是,为什么会有所不同?要求列表末尾的空值有什么意义?
答案 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)