Why Clojure idiom prefer to return nil instead of empty list like Scheme?
从另一个问题的评论中,有人说Clojure惯用语更喜欢返回nil而不是Scheme中的空列表。 这是为什么?
喜欢,
1 | (when (seq lat) ...) |
代替
1 2 | (if (empty? lat) '() ...) |
我可以想到一些原因:
-
逻辑上的区别。在Clojure中,无表示无/无价值。而'()"空列表是一个值-它恰好是一个值,它是一个空列表。在概念上和逻辑上,区分两者通常很有用。
-
适合JVM-JVM对象模型支持空引用。而且很多Java API返回null表示"无"或"未找到值"。因此,为确保轻松的JVM互操作性,Clojure以类似的方式使用nil是有意义的。
-
懒惰-此处的逻辑非常复杂,但是我的理解是,对Clojure的惰性序列使用nil表示"无列表"效果更好。由于默认情况下Clojure是一种惰性函数式编程语言,因此使这种用法成为标准是有意义的。有关更多说明,请参见http://clojure.org/lazy。
-
"虚假"-在编写检查集合的条件代码时使用nil表示"无",也表示" false"很方便-因此您可以编写
(if (some-map :some-key) ....) 之类的代码来测试哈希映射是否包含给定键的值。 -
性能-测试nil比检查列表是否为空更有效...因此,将此习语用作标准可以导致更高性能的惯用代码
请注意,Clojure中仍有一些函数确实返回一个空列表。一个例子是休息:
1 2 | (rest [1]) => () |
关于休息与下一个的问题将详细说明为什么会这样。
还要注意,集合类型和nil的并集构成一个monoid,而将monoid加和nil则与monoid 0串联在一起。因此,nil会将空列表语义保留在串联之下,同时还表示错误或"丢失"的值。
Python是另一种语言,其中常见的monoid身份表示错误的值:0,空列表,空元组。
摘自Clojure的喜悦
Because empty collections act like
true in Boolean contexts, you need an idiom for testing whether there's anything in a collection to process. Thankfully, Clojure provides such a technique:
1
2
3
4
5 (seq [1 2 3])
;=> (1 2 3)
(seq [])
;=> nil
在其他Lisps中,例如Common Lisp,空列表用于表示
自从我写了评论以来,我会写一个答案。 (skuro的答案提供了所有信息,但可能太多了)
请参阅以下示例:
(如果为假
'()
(做(println 1)
(println 2)
(println 3)))
你可以写
(当为true时
(println 1)
(println 2)
(println 3))
没有那么不同,但是我认为它更好阅读。
附言
并不是说有称为