clojure - Why prefer seq over non-empty as a predicate? -
the docstring empty? says "please use idiom (seq x) rather (not (empty? x))". mistermetaphor points out using seq predicate can make sense when used in if-let:
(if-let [s (seq might-be-empty)] (fn-for-non-empty-seq s) (fn-for-empty-seq)) should use seq test non-emptiness in general, though? seq may convert argument different form. example:
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 that seems waste of cycles if want test non-emptiness, , don't need new binding, or if don't need conversion before binding. wouldn't not-empty better choice in such cases? returns nil if argument empty, , argument unchanged if non-empty.
(if (not-empty []) "more do" "all done")
first, check out definition of empty?:
(defn empty? "returns true if coll has no items - same (not (seq coll)). please use idiom (seq x) rather (not (empty? x))" {:added "1.0" :static true} [coll] (not (seq coll))) so empty? is (not (seq coll)). that's why it's discouraged complement empty?, because doing double negation on seq.
now see not-empty
(defn not-empty "if coll empty, returns nil, else coll" {:added "1.0" :static true} [coll] (when (seq coll) coll)) surprise, uses seq test of non-emptiness too. not-empty is useful if type matters -- nth performance on vectors, conj behavior, etc. -- because return non-empty colls is. used predicate though, wrapping seq.
don't worry seq being heavy-handed though. little more return iterator. not convert entire data structure.
Comments
Post a Comment