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

Popular posts from this blog

python - Subclassed QStyledItemDelegate ignores Stylesheet -

java - HttpClient 3.1 Connection pooling vs HttpClient 4.3.2 -

SQL: Divide the sum of values in one table with the count of rows in another -