我在Clojure 1.2.1中看到了这种行为:
user=> (type '(1 2))
clojure.lang.PersistentList
user=> (type `(1 2)) ;; notice syntax-quote
clojure.lang.Cons
user=> (type '(1))
clojure.lang.PersistentList
user=> (type `(1))
clojure.lang.PersistentList
我希望`(1)成为一个缺点,就像`(1 2)那样。
我也尝试过:
user=> (type (cons 1 nil))
clojure.lang.PersistentList
user=> (type (cons 1 `()))
clojure.lang.Cons
user=> (type (cons 1 '()))
clojure.lang.Cons
user=> (type (cons 1 []))
clojure.lang.Cons
那么`(1)和(cons 1 nil)成为PersistentLists的原因是什么?
答案 0 :(得分:4)
如果你关心差异,你的程序是不正确的。在(seq? x)
返回true的意义上,它们都是seqs;其余的是你不应该依赖的实施细节。
答案 1 :(得分:4)
就像amalloy说的那样,你不应该针对那些确切的类型进行编程,而是针对seq
抽象。
但是,我想我可以猜一下原因。 Clojure表单生成PersistentList
最终调用RT.java,特别是cons(Object x, Object coll)
方法。它以一个非常奇怪的检查开始:if(coll == null) return new PersistentList(x)
,如果检查没有通过,它会创建一个Cons
对象。如果你看earlier versions of the code,你可以找到:
static public IPersistentCollection cons(Object x, IPersistentCollection y) {
if(y == null)
return new PersistentList(x);
return y.cons(x);
}
因此,在该函数的早期版本中,调用被调度到第二个参数的cons
方法,因此第二个参数为null
的情况(即nil
in Clojure)需要特殊处理。更高版本不执行该调度(或实际执行但以不同的方式执行,可能支持更多种类的集合类型),但检查已保留,因为它不会破坏任何正确编写的代码。