为什么Clojure成语更喜欢返回nil而不是像Scheme这样的空列表?

Pau*_*Lam 14 idioms clojure

对另一个问题的评论中,有人说Clojure成语更喜欢返回nil而不是像Scheme中的空列表.这是为什么?

喜欢,

(when (seq lat) ...)
Run Code Online (Sandbox Code Playgroud)

代替

  (if (empty? lat)  
    '() ...)
Run Code Online (Sandbox Code Playgroud)

mik*_*era 23

我可以想到几个原因:

  • 逻辑区别.在Clojure中,没有任何意义/缺乏价值.而'()'空列表一个值 - 它恰好是一个空列表的值.它在概念和逻辑上通常很有用,可以区分这两个.

  • 适合JVM - JVM对象模型支持空引用.而且很多Java API都返回null表示"没有"或"找不到值".因此,为了确保简单的JVM互操作性,Clojure以类似的方式使用nil是有意义的.

  • 懒惰 - 这里的逻辑很复杂,但我的理解是使用nil作为"无列表"可以更好地使用Clojure的懒惰序列.由于Clojure默认是一种惰性函数式编程语言,因此这种用法是标准的.有关其他说明,请参见http://clojure.org/lazy.

  • "Falsiness" - 在编写检查集合的条件代码时,使用nil表示"无"并且表示"假"也很方便 - 因此您可以编写代码(if (some-map :some-key) ....)来测试hashmap是否包含给定键的值.

  • 性能 - 测试nil比检查列表以查看它是否为空更有效...因此采用这个成语作为标准可以导致更高性能的惯用代码

请注意,Clojure中仍然存在一些返回空列表的函数.一个例子是休息:

(rest [1])
=> ()
Run Code Online (Sandbox Code Playgroud)

关于休息与下一个问题的这个问题详细解释了为什么这是......


Tho*_*ood 7

还要注意,集合类型和nil的并集形成一个monoid,连接monoid加上nil和monoid零.因此,nil将空列表语义保持在连接状态,同时还表示错误或"缺失"值.

Python是另一种常见的monoid身份表示错误值的语言:0,空列表,空元组.

  • 你知道如果你有加法,任何n + 0 = n?如果你有逻辑或任何n或true = n?如果你在Clojure中有列表连接,那么(concat n nil)= n?所以在运营中存在这种"缺失事物"的模式.Clojure使用nil来表示许多情况下"缺失"的想法,因此您可以使常见算法(例如树步行者)更通用和更清晰. (6认同)

wil*_*-ob 5

摘自Clojure的喜悦

由于空集合的行为类似于true布尔上下文,因此您需要一个习惯用法来测试集合中是否有任何要处理的东西。幸运的是,Clojure提供了这样一种技术:

(seq [1 2 3])
;=> (1 2 3)

(seq [])
;=> nil
Run Code Online (Sandbox Code Playgroud)

在其他Lisps中,例如Common Lisp,空列表用来表示nil。这称为nil punning,仅在空列表为falsey时才可行。返回nil这里是Clojure重新引入零校正的方式。