Mars
Mars

Reputation: 8854

Why prefer seq over non-empty as a predicate?

The docstring for empty? says "Please use the idiom (seq x) rather than (not (empty? x))". MisterMetaphor points out that using seq as a 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 I really use seq to test for non-emptiness in general, though? seq may convert its argument to a different form. For 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 like a waste of cycles if just want to test for non-emptiness, and don't need a new binding, or if I don't need the conversion before the binding. Wouldn't not-empty be a better choice in such cases? It returns nil if its argument is empty, and its argument unchanged if non-empty.

(if (not-empty [])
  "more to do"
  "all done")

Upvotes: 11

Views: 3117

Answers (1)

A. Webb
A. Webb

Reputation: 26446

First, check out the definition of 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)))

So empty? is (not (seq coll)). That's why it's discouraged to complement empty?, because you are doing a double negation on seq.

Now see not-empty

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

Surprise, it uses seq as the test of non-emptiness too. This not-empty is useful if the type matters -- nth performance on vectors, conj behavior, etc. -- because it does return non-empty colls as is. Used as just a predicate though, it would only be wrapping seq.

Don't worry about seq being heavy-handed though. It does little more than return an iterator. It does not actually convert the entire data structure.

Upvotes: 25

Related Questions