为什么更喜欢seq而不是非空作为谓词?

时间:2014-02-06 05:38:58

标签: clojure

empty?的文档字符串表示"请使用成语(seq x)而不是(not(empty?x))"。 MisterMetaphor指出在seq中使用if-let时,使用(if-let [s (seq might-be-empty)] (fn-for-non-empty-seq s) (fn-for-empty-seq)) 作为谓词是有意义的:

seq

但是,我真的应该使用seq来测试一般的非空虚吗? user=> (class (lazy-seq '(1 2 3))) clojure.lang.LazySeq user=> (class (seq (lazy-seq '(1 2 3)))) clojure.lang.PersistentList user=> (class (map inc [1 2 3])) clojure.lang.LazySeq user=> (class (seq (map inc [1 2 3]))) clojure.lang.ChunkedCons 可以将其参数转换为其他形式。例如:

not-empty

如果只是想测试非空虚,并且不需要新的绑定,或者在绑定之前我不需要转换,这似乎是浪费周期。在这种情况下,nil不是更好的选择吗?如果参数为空,则返回(if (not-empty []) "more to do" "all done") ,如果非空,则返回其参数。

{{1}}

1 个答案:

答案 0 :(得分:16)

首先,查看empty?的定义:

(defn empty?
  "Returns true if coll has no items - same as (not (seq coll)).
  Please use the idiom (seq x) rather than (not (empty? x))"
  {:added "1.0"
  :static true}
  [coll] (not (seq coll)))

所以empty? (not (seq coll))。这就是为什么不鼓励补充empty?,因为你在seq上做了双重否定。

现在看not-empty

(defn not-empty
  "If coll is empty, returns nil, else coll"
  {:added "1.0"
   :static true}
  [coll] (when (seq coll) coll))

令人惊讶的是,它也使用seq作为非空虚的测试。如果类型很重要,not-empty 有用 - nth对向量的表现,conj行为等等 - 因为它确实将非空的colls返回为是。仅用作谓词,它只包装seq

不要担心seq会变得笨手笨脚。它只是返回一个迭代器。它实际上并不转换整个数据结构。