Learning Clojure #2: contains?

4

I spent 30 minutes today learning that contains? has surprising (to me at least) behavior on indexed collections. I expected it to tell me whether the vector contains an item and indeed this is how it works on collections like lists, sets, maps, etc.

For example:

user=> (contains? #{ "a" "b"} "a")
true
user=> (contains? { :a 1 :b 2 } :a)
true
user=> (contains? ["a" "b" ] "a")
false

What? Check the docs:

user=> (doc contains?)
-------------------------
clojure.core/contains?
([coll key])
  Returns true if key is present in the given collection, otherwise
  returns false.  Note that for numerically indexed collections like
  vectors and Java arrays, this tests if the numeric key is within the
  range of indexes. 'contains?' operates constant or logarithmic time;
  it will not perform a linear search for a value.  See also 'some'.

So for structures like vectors and arrays, the contains? function expects a numerical argument that is an index, not an item.

user=> (contains? ["a" "b"] 0)
true
user=> (contains? ["a" "b"] 1)
true
user=> (contains? ["a" "b"] 2)
false

I don’t have a better solution at hand for how to do this with vectors and arrays. I’d love to see one.

Update from @fogus:

user=> (some #{"b"} ["a" "b"])
"b"
user=> (some #{"d"} ["a" "b"])
nil

For the purposes of logical true/false, the “b” will evaluate to true. I’ll just say that’s pretty obscure in my book.

Update #2: Some useful info here too on this subject. Thanks @wmacgyver.

Comments

4 Responses to “Learning Clojure #2: contains?”
  1. terry says:

    I understand now why I struggled so much with Lisp in school. The behavior is pretty bizarre and unintuitive even for such a simple use case.

  2. Alex Miller says:

    I think in this case this is a Clojure-ism more so than a Lisp-ism.

  3. Scott Bale says:

    Nice – I was googling for contains? help and this page came up. The ironing is delicious.

  4. Matthew says:

    I think using “some” will work in most cases except if you want to test if nil itself is in the vector

Speak Your Mind

Tell us what you're thinking...
and oh, if you want a pic to show with your comment, go get a gravatar!