Why prefer seq over non-empty as a predicate?

clojure

Solution

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.

Problem

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") ```

Original source

Related problems