在 SBCL REPL 中,为什么输入的'(nil . nil)
计算结果为(nil)
而不仅仅是nil
?
如果空列表是 cons 单元的两个“元素”所在的列表nil
,为什么它们不一样?
我对此的假设是 SBCL 做出以下评估:
(car '()) => nil
(cdr '()) => nil
(car '(nil . nil)) => nil
(cdr '(nil . nil)) => nil
但是:
'() => nil
'(nil . nil) => (nil)
在 SBCL REPL 中,为什么输入的'(nil . nil)
计算结果为(nil)
而不仅仅是nil
?
如果空列表是 cons 单元的两个“元素”所在的列表nil
,为什么它们不一样?
我对此的假设是 SBCL 做出以下评估:
(car '()) => nil
(cdr '()) => nil
(car '(nil . nil)) => nil
(cdr '(nil . nil)) => nil
但是:
'() => nil
'(nil . nil) => (nil)
car
如果作为参数给出cdr
则返回。让我们先了解一下这个词,看看您实际看到的值是什么。nil
nil
nil
car
并cdr
得到一个空列表,所以我们返回nil
, 或()
。现在
(nil . nil)
是(() . ())
。也就是说,它是一个 cons cell,其 car 和 cdr 都是nil
。. ()
当cons 单元格末尾有 a 时,我们可以通过省略尾随的 来在符号上缩短它nil
。这只是符号上的方便,所以通过我们的符号(() . ())
可以写成(())
, 或(nil)
。请注意,这不会改变该值。最明确的书写方式仍然是(() . ())
,但我们也可以将其写得更短以提高可读性。这是不正确的。空列表根本不是缺点单元格。空列表是原子
nil
。它是一个符号,就像'foo
or'pizza
或 一样'common-lisp
。这只是我们选择用于此目的的一个符号。但nil
没有汽车或 cdr 细胞。碰巧的是,让(car nil)
和(cdr nil)
benil
作为算法的极端情况通常很方便,因此函数car
和cdr
在 上有特殊的行为nil
。但nil
不是一个缺点细胞。根据系统类
LIST
,list
类型可以描述为因此Common Lisp 中的列表被定义为“cons 单元格或特殊值
nil
”。值得注意的是,nil
它本身并不是一个缺点细胞。这不是 SBCL 特有的。它是在 Common Lisp 标准中定义的。
cons 单元中的 NIL
请注意,
NIL
和()
是同一个对象,只是写法不同:另请注意,您不评估
(nil . nil)
,而是评估'(nil . nil)
。前者不是有效的 Lisp 代码。后者是,因为它是一个语法正确的引用 s 表达式。(nil . nil)
等于(nil)
,但写法不同。cons 结构是相等的。上面的 s 表达式是相等的:
NIL 的 CAR 和 C****R
当使用空列表(-> 符号/列表)调用时, Common Lisp 的所有cxxxr操作都定义为返回:
NIL
NIL
请参见访问器 CAR、CDR、CAAR、CADR、CDAR、CDDR、CAAAR、CAADR、CADAR、CADDDR、CDAAR、CDADR、CDDAR、CDDDR、CAAAAR、CAAADR、CAADAR、CAADDR、CADAAR、CADADR、CADDAR、CADDDR、CDAAAR、CDAADR、 Common Lisp 标准中的CDADAR、CDADDR、CDDAAR、CDDADR、CDDDAR、CDDDDR 。
car
Common Lisp 和Scheme 语言之间函数的差异这和编程语言Scheme不同,哪里
(car '())
有错误。例如,参见R7RS 小型汽车。另请注意,Scheme没有
nil
. 它在语言中是未定义的,因此与空列表 不同()
。在Scheme 中评估空列表()
是一个错误。以下Scheme表达式计算结果为错误:
上述三个表达式
NIL
在 Common Lisp 中的计算结果为。你在这里犯的一个严重错误是以错误的方式得到了暗示。特别是,在 Common Lisp 中,空列表的
car
andcdr
of 返回空列表是正确的,但任何为 true 的对象都不是空列表。事实上,很明显这不可能是真的,因为空列表对象是唯一的,而(eq (cons '() '()) (cons '() '()))
必须是假的。因此,虽然“成为空列表”意味着(在 Common Lisp 中!)采用
car
/cdr
返回空列表,但反之则不然。