Reputation: 25269
I'm following this example: http://groups.google.com/group/clojure/browse_thread/thread/99b3d792b1d34b56
(see the last reply)
And this is the cryptic error that I get:
Clojure 1.2.1
user=> (def m {:a "x" :b "y" :c "z" :d "w"})
#'user/m
user=> (filter #(some % [:a :b]) m)
java.lang.IllegalArgumentException: Key must be integer
(user=>
Also I don't understand why this would even work. Isn't (some ...) going to return the first matching value, "x", every time? I'm a total noob at clojure and just trying to learn.
Please enlighten me.
Upvotes: 10
Views: 14292
Reputation: 1085
If you "iterate" over a map, you'll get key-value pairs rather than keys. For instance,
user=> (map #(str %) {:a 1, :b 2, :c 3})
("[:a 1]" "[:b 2]" "[:c 3]")
Thus your anonymous function tries to evaluate (some [:a "x"] [:a :b])
which clearly does not work.
The ideomatic solution is to use select-keys
as mentioned in another answer.
Upvotes: 8
Reputation: 1109
(filter
(fn [x]
(some #{(key x)} [:a :b])) m)
Would do the same using filter
and some
(but uglier and slower).
This works by filter all from m
if some [:a :b]
is in the set #{(key x)}
(i.e. using a set as predicate) then return the map entry.
Upvotes: 1
Reputation: 25269
I guess I just needed to read the docs more:
(select-keys m [:a :b])
Although I'm still not sure what the intention was with the example I found...
Upvotes: 31