在 Scheme 中,`nil` 和 `null` 有什么区别?
In Scheme, what is the difference between `nil` and `null`?
在《小小阴谋家》中,null
用来指代空表()
。但我在 Scheme 的错误消息中也看到了称为 nil
的空列表,例如正在做:
(car ())
原因:
Error: Attempt to apply car on nil [car]
[1]
这听起来像是将 ()
称为 nil
。
[1] 使用 replit.com 的 BiwaScheme 解释器版本 0.6.4
此题与What is the exact difference between null and null in common lisp类似。这是不同的,因为正如此处的答案所指出的,Common Lisp 和 Scheme 在处理 nil
和 null
.
方面存在差异
不同 Lisp 之间的区别在于它们如何处理 true、false 和 nil。
在 Common Lisp 中,我们有 t
表示真,nil
表示假,尽管实际上除了 nil
之外的所有内容都是真的。如果列表为空,或者 find
什么也没找到,我们有 nil
可以直接测试。技术术语是 nil punning
.
'() ; => NIL
(= 1 2) ; => NIL
(if '() "full" "empty") ; => "empty"
(find 5 '(1 2 3 4)) ; => NIL
(if (find 5 '(1 2 3 4)) "found" "not found" ; => "not found"
Clojure 的做法不同。有一个官方真值 true
,还有两个假值,false
和 nil
- 除了 false
和 nil
之外的所有值也都是真值。空列表不再是nil
,空列表需要单独测试,有empty?
。值 nil
更像是 C 中的 void
。更好还是更差? - 你来决定。
'() ; => ()
(= 1 1) ; => true
(= 1 2) ; => false
(if '() "full" "empty") ; => "full"
(if (empty? '()) "empty" "full") ; => "empty"
(if nil "full" "empty") ; => "empty"
(if (println "Hello world") "full" "empty") ; => empty
Scheme 在意图上更接近 Clojure。这里有一个假值,#f
。空列表不再是nil
,空列表需要单独测试,有null?
.
(= 1 1) ; => #t
(= 1 2) ; => #f
(null? '()) ; => #t
(null? 'nil) ; => #f
因此,null
是空列表的另一个名称,但 nil
或 'nil
不是。
null ; => ()
nil ; => cannot reference an identifier before its definition
'nil ; => nil
(car ())
怎么样?您的方案 returns nil
来自评估 ()
,这就是 car
所抱怨的。我的Scheme,Racket博士,根本拒绝播放,说空表中缺少表达式。
我认为您在错误消息中看到的是历史产物。
在传统的 Lisp 语言中,nil
既是空列表又是布尔值 false,并且在其他方面相当特殊(例如,它是 也是 符号,这很奇怪)。
所以特别是 ()
和 nil
在这样的 Lisp 中是同一个对象, (not nil)
是真的, (not '())
也是真的(事实上(not ())
既合法又正确)。空列表对象的谓词是 null
(也许应该是 nullp
,但历史表明它就是这样)并且 (null nil)
与 (null '())
和 [=20 一样为真=].
还有一些疑问 (car nil)
aka (car '())
aka (car ())
应该做什么.传统上答案是这样很好,(car nil)
是 nil
。如果你聪明的话,这会给你一个非常巧妙的 nil
实现。
Scheme 现在取消了所有这些双关语:
- 有一个唯一的假对象是
#f
/ #false
,它不是空列表;
- 所有其他对象都为真,因此
(not x)
仅在 x
为 #f
时为真;
- 有一个唯一的空列表对象,它是
()
,它不是 #f
,因此是 true;
- 这个对象的谓词是
null?
,所以(null? '())
是真的,但是(null? #f)
是假的;
car
和()
的cdr
是错误的;
nil
只是一个符号,在语言中没有任何特殊地位。
我不认为 ()
有一个名字是标准的,但显然给它一个名字可能会有用,null
很好:例如,Racket 就是这样做的。
所以在 Scheme 中,nil
消失了,空列表和布尔值 false 之间的双关语也随之消失。
但是很多实现Schemes的人都知道nil
就是人们所说的空表。所以当他们写错误信息的时候,他们写的是 nil
而他们的意思是 ()
,因为很长一段时间以来每个人都这么叫 ()
。
我认为,这就是您在这里看到的。
在《小小阴谋家》中,null
用来指代空表()
。但我在 Scheme 的错误消息中也看到了称为 nil
的空列表,例如正在做:
(car ())
原因:
Error: Attempt to apply car on nil [car]
[1]
这听起来像是将 ()
称为 nil
。
[1] 使用 replit.com 的 BiwaScheme 解释器版本 0.6.4
此题与What is the exact difference between null and null in common lisp类似。这是不同的,因为正如此处的答案所指出的,Common Lisp 和 Scheme 在处理 nil
和 null
.
不同 Lisp 之间的区别在于它们如何处理 true、false 和 nil。
在 Common Lisp 中,我们有 t
表示真,nil
表示假,尽管实际上除了 nil
之外的所有内容都是真的。如果列表为空,或者 find
什么也没找到,我们有 nil
可以直接测试。技术术语是 nil punning
.
'() ; => NIL
(= 1 2) ; => NIL
(if '() "full" "empty") ; => "empty"
(find 5 '(1 2 3 4)) ; => NIL
(if (find 5 '(1 2 3 4)) "found" "not found" ; => "not found"
Clojure 的做法不同。有一个官方真值 true
,还有两个假值,false
和 nil
- 除了 false
和 nil
之外的所有值也都是真值。空列表不再是nil
,空列表需要单独测试,有empty?
。值 nil
更像是 C 中的 void
。更好还是更差? - 你来决定。
'() ; => ()
(= 1 1) ; => true
(= 1 2) ; => false
(if '() "full" "empty") ; => "full"
(if (empty? '()) "empty" "full") ; => "empty"
(if nil "full" "empty") ; => "empty"
(if (println "Hello world") "full" "empty") ; => empty
Scheme 在意图上更接近 Clojure。这里有一个假值,#f
。空列表不再是nil
,空列表需要单独测试,有null?
.
(= 1 1) ; => #t
(= 1 2) ; => #f
(null? '()) ; => #t
(null? 'nil) ; => #f
因此,null
是空列表的另一个名称,但 nil
或 'nil
不是。
null ; => ()
nil ; => cannot reference an identifier before its definition
'nil ; => nil
(car ())
怎么样?您的方案 returns nil
来自评估 ()
,这就是 car
所抱怨的。我的Scheme,Racket博士,根本拒绝播放,说空表中缺少表达式。
我认为您在错误消息中看到的是历史产物。
在传统的 Lisp 语言中,nil
既是空列表又是布尔值 false,并且在其他方面相当特殊(例如,它是 也是 符号,这很奇怪)。
所以特别是 ()
和 nil
在这样的 Lisp 中是同一个对象, (not nil)
是真的, (not '())
也是真的(事实上(not ())
既合法又正确)。空列表对象的谓词是 null
(也许应该是 nullp
,但历史表明它就是这样)并且 (null nil)
与 (null '())
和 [=20 一样为真=].
还有一些疑问 (car nil)
aka (car '())
aka (car ())
应该做什么.传统上答案是这样很好,(car nil)
是 nil
。如果你聪明的话,这会给你一个非常巧妙的 nil
实现。
Scheme 现在取消了所有这些双关语:
- 有一个唯一的假对象是
#f
/#false
,它不是空列表; - 所有其他对象都为真,因此
(not x)
仅在x
为#f
时为真; - 有一个唯一的空列表对象,它是
()
,它不是#f
,因此是 true; - 这个对象的谓词是
null?
,所以(null? '())
是真的,但是(null? #f)
是假的; car
和()
的cdr
是错误的;nil
只是一个符号,在语言中没有任何特殊地位。
我不认为 ()
有一个名字是标准的,但显然给它一个名字可能会有用,null
很好:例如,Racket 就是这样做的。
所以在 Scheme 中,nil
消失了,空列表和布尔值 false 之间的双关语也随之消失。
但是很多实现Schemes的人都知道nil
就是人们所说的空表。所以当他们写错误信息的时候,他们写的是 nil
而他们的意思是 ()
,因为很长一段时间以来每个人都这么叫 ()
。
我认为,这就是您在这里看到的。