I am a newbie for clojure and a little bit confused with the use of contains? form to different data structures.
The result of applying contains to a vector, set or a map is just what I expect, it tests if a key (or index) is present in the collection. But when it comes to a list, such as
(def li '(1 2 3)) ; define a list
(contains? li 1) ; returns false !!??
I know it is NOT that straightforward to understand how contains? works with a list, since its document says the implementation operates in a constant or log time. So here it doesnt really make sense to test in less than log time if 1 is in a list or its index range.
But in that case why doesnt it just raise an exception like when applying assoc with a list. In the assoc case the philosophy is the same – the assoc should NOT be applied to a list since it doesnt support fast-enough random-access of its elements.
I feel it inconvenient because a lot of forms in clojure return a general collection as the results, such as (vals a-map), so to test if an element exists in the value set of a map, different methods give different results – but to me they are just the different ways of saying the SAME thing.
(def a-map {:one 1 :two 2})
(contains? (vals a-map) 1) ; returns false!!
(contains? (set (vals a-map)) 1); returns true!!
So after the long explanation, my question is – what is the rational behind this design? How should we say it natively when we want to test if an element is in a value set of a map in clojure, i.e., more importantly, how should I convince myself so that I will not make stupid bugs in practice? Thanks!
The source code reveals that for clojure up to and including version 1.4
contains?always return false for lists (it falls through to line 713).In the latest 1.5 beta it will throw an exception.