29
votes

I want to write a function that would return the boolean true if the given collection is not empty and false otherwise.

I could either do

defn ..
(boolean (seq coll))

or

defn ..
(not (empty? coll))

As I am new to clojure I was initially inclined to go with #2 (more readable), but the clojure api reference for empty? explicitly says use the idiom (seq coll) instead of (not (empty? coll)), maybe to avoid double negation.

I want to know what is the clojure way to check if a collection is non-empty and return a boolean true/false.

4

4 Answers

28
votes

According to Joy of Clojure, nil punning with seq is idiomatic:

(defn print-seq [s]
  (when (seq s)
    (prn (first s))
    (recur (rest s))))

"...the use of seq as a terminating condition is the idiomatic way to test whether a sequence is empty. If we tested [in the above example] just s instead of (seq s), then the terminating condition wouldn't occur even for empty collections..."

12
votes

The passage from empty?'s docstring which you mentioned means in particular that such a nonempty? function should never be necessary, or even particularly useful, because seq can always stand in for it in Boolean contexts, which in pure Clojure code it can.

If you feel compelled to write such a function nonetheless, I'll say that I like the first approach better. empty? is built on seq anyway, so there's no avoiding calling it; just casting the result to Boolean seems cleaner than two trips through not. For other options, see e.g. nil?, false? (I still prefer the cast).

Incidentally, why do you want to write this...? For calling a Java method with a boolean argument perhaps? In that case, I think the cast would express the intention nicely.

Update: An example to illustrate the latter point:

  1. A simple Java class:

    public class Foo {
      public static boolean foo(boolean arg) {
        return !arg;
      }
    }
    
  2. Some Clojure client code:

    (Foo/foo nil)
    ; => NullPointerException
    (Foo/foo (boolean nil))
    ; => true
    
4
votes

In addition to Michal Marczyk's excellent answer, I'll point out that there is a specific not-empty function:

http://clojure.github.io/clojure/clojure.core-api.html#clojure.core/not-empty

but it doesn't do exactly what you ask for. (Though it will work in most situations).

Not-empty returns nil if the collection is empty, and the collection itself if the collection is not empty. For predicate tests, that will function well. If you actually need true and false values, then (not (empty? x)) is what you're after.

0
votes

If you need a boolean, I think (comp not seq) has a nice ring to it.

Example usage:

((comp not seq) coll)

And if you need to store it as a fn for later:

(def not-empty' (comp not seq))