Every once in a while someone asks on the Clojure group why `(contains? [:a :b :c] :a)` returns `false`. In the following heated discussions about semantics (yeah! a discussion about semantics!) people always suggest to add a `linear-search` to Clojure. What they miss: `linear-search` is already there.

The confusion

The confusion with `contains?` is explained quite simply: people expect it to work on keys with maps and on values with vectors.

``````; Matches expectations
user=> (contains? {:a 1 :b 2 :c 3} :a)
true
; Surprises people
user=> (contains? [:a :b :c] :a)
false
; More surprised looks
user=> (contains? [:a :b :c] 0)
true
``````

However, reading the last sentence of the previous paragraph should already explain the above behaviour: vectors are keyed by number, not the item value! So how can `contains?` work as people expect without being completely inconsistent with its contract?

The clarification

So `contains?` does not a linear search. However another function does: `some`. A perfectly normal, idiomatic Clojure version of the desired behaviour is the following:

``````user=> (some #{:a} [:a :b :c])
:a
user=> (some #{:d} [:a :b :c])
nil
``````

This will do the trick. With one little exception: in case boolean `false` and `nil` are valid values in our collection we are in trouble.

``````user=> (some #{false} [:a false :b])
false
``````

Doh! In this case we have to use `#(= % false)`:

``````user=> (some #(= % false) [:a false :b])
true
``````

Both versions are perfectly idiomatic Clojure.

Upshot

Today we will close with the words of Chris Houser who puts things quite on the spot.

What is the drawback of the `(some #{:y} [:x :y :z])` idiom? Is it too verbose? Too slow? Too flexible? Too good a re-use of existing functionality? Too helpful in opening ones eyes to the possibilities of sets and higher order functions?