4

我不明白为什么我们需要nil[1] 来处理cons项目的序列(所谓的正确列表)。在我看来,我们可以通过单独使用所谓的不正确列表(cons没有结尾的 -ed 对nil)来实现相同的目标。由于 Lisps [2] 已经提供了一个原始过程来区分 apair?和原子(一些实现甚至提供atom?),当在列表上定义过程时,例如,length我可以只用点对做同样的事情,如下所示:

(define len
  (lambda (l)
    (cond ((pair? l) (+ 1 (len (cdr l))))
          (else 1) ) ) )

很明显,我们可以将这个过程应用到一个不合适的列表上,比如'(1 . (2 . 3))得到预期的答案3,这与传统的不同(length '(1 2 3))

我想听听任何为nil. 提前致谢。

nil[1] 让我们忽略/NIL和之间'()的争论()

[2] 这里指的是 Lisp 语言家族。

4

2 回答 2

20

使用没有nil(or '()) 的列表就像在没有零的情况下进行算术一样。只使用没有 的对nil,我们将如何表示一个空列表或单例列表'(1)

更糟的是:由于列表不必是原子列表,但可以包含其他列表,我们将如何表示嵌套列表'(1 2 (3 4))?如果我们进行以下转换:

'(3 4) => '(3 . 4)
'(1 2 x) => '(1 . (2 . x)) == '(1 2 . x)

我们得到:

'(1 2 (3 4)) => '(1 . (2 . (3 . 4))) == '(1 2 3 . 4)

但是也:

'(1 2 3 4) => '(1 . (2 . (3 . 4))) == '(1 2 3 . 4)

因此,仅使用对而不使用对构造列表nil会阻止我们区分嵌套列表结构和平面列表,至少在列表的末尾是这样。您仍然可以将嵌套列表作为除最后一个之外的任何元素包含在内,因此现在对列表的元素可以是什么有一个奇怪且任意的限制。

更理论上,正确的列表是一种归纳定义的数据类型:一个列表或者是空列表,或者它有一个first元素,可以是任何东西,而 arest总是相同方式定义的另一个列表。去掉空列表,现在你有了一个数据类型,它rest 可能是另一个列表,也可能是列表的最后一个元素。我们只能通过将它传递给 来判断pair?,这会导致上面的嵌套列表出现问题。保留nil让我们拥有任何我们喜欢的列表元素,并允许我们区分1'(1)'((1))

于 2012-01-30T10:46:23.410 回答
1

你需要它来代表“无”。

于 2012-01-30T20:45:14.783 回答