Mark Needham

Thoughts on Software Development

Clojure: Checking for a nil value in a collection

with 3 comments

Something which I wanted to do recently was write a function that would indicate whether a collection contained a nil value.

I initially incorrectly thought the ‘contains?‘ function was the one that I wanted:

(contains? '(1 nil 2 3) nil)
=> false

I thought it would work the same as the Java equivalent but that function actually checks whether a key exists in a collection rather than a value. It’s more useful when dealing with maps.

There’s more discussion on the consistency of the API on the mailing list.

Luckily the documentation guides us towards the ‘some‘ function:

My first attempt was to write an anonymous function to check if there was a ‘nil’ in the list:

(some #(= % nil) '(1 nil 2 3))
=> true
(some #(= % nil) '(1  2 3))
=> nil

fogus showed me an even better way by making use of the built in ‘nil?‘ function:

(some nil? '(1 nil 2 3))

Another approach would be to make use of the Java ‘contains’ method as Philip Schwarz pointed out:

(.contains '(1 nil 2 3) nil)
=> true

I noticed that when you use Java methods in Clojure with collections then the result will either be ‘true’ or ‘false’ whereas when you use Clojure built in functions then it’s more likely to be ‘true’ or ‘nil’.

I guess this is linked to the idea that ‘nil’ is false in Clojure so it doesn’t make much difference what the return value is.

When I’m using a language I’ve got into the habit of just trying out the API in the way that I expect it to work rather than paying a lot of attention to what the API documentation says.

I think this is something I’ll need to work out to avoid much frustration!

Be Sociable, Share!

Written by Mark Needham

November 21st, 2009 at 10:11 pm

Posted in Clojure

Tagged with

  • I don’t think Clojure prefers nil over false. Note that it’s `some`, not `some?`: it isn’t a predicate for seeing whether something in the collection satisfies another predicate, rather it’s a function for getting some element that satisfies a given predicate. (There is, however, no predicate for doing this job, while there are `every?`, `not-every?`, and `not-any?`, so it ends up used in place of a predicate often, thanks to nil being falsey.)

  • Oops … clearly I haven’t been writing enough Clojure recently. I stick by my assertion that `some` isn’t a predicate, but it returns the first logically true result of applying the first argument (not the value that yielded the logical true, as I previously stated). Given this, it will always just return true or nil if you give it a true predicate function as the first argument.

    There are these though:

    (some #{:foo :bar} [:baz :bar]) => :bar

    (some {:a “Aye” :b “Bee”} [:c :b]) => “Bee”

  •  We’re not even on the same project anymore and you still helped me! 🙂