1
votes

In clojure you can use both maps and keys as look up functions hence ({:a 1 :b 2} :a) and (:a {:a 1 :b 2}) are both viable lookup functions.

Why then can you use a map as a lookup function for a compound-key but not the other way around?

This means ({[:compound :mebaby] 1} [:compound :mebaby]}) will return 1, but ([:compound :mebaby] {[:compound :mebaby] 1}) will throw an error.

3
You may want to read this chapter of Clojure Cookbook. Maybe the surrounding ones as well.D-side

3 Answers

2
votes

Keywords implement IFn as one of their features to make them convenient to use as keys. The fn they implement is a lookup for themselves in an associative structure argument. This is not the case for collections like your vector because they implement IFn to do lookup in themselves at the argument key.

So ({[:compound :mebaby] 1} [:compound :mebaby]}) asks the map what the value is for the key [:compound :mebaby], which exists. But ([:compound :mebaby] {[:compound :mebaby] 1}) asks the vector what the value at the index {[:compound :mebaby] 1} is. That's not an integral number, so it can't be an index/key in a vector and throws an error.

0
votes

The reason is that: your compound-key is no longer a keyword. It is now a vector, though still an IFn, it only takes integers, say i, as arguments, returning the ith element of the vector.

I suspect what you really want is to extract value from a nested map, like extracting the String "c" from {:a {:b "c"}}. If so, these two forms are equivalent:

(get-in {:a {:b "c"}} [:a :b])
;=> "c"
((comp :b :a) {:a {:b "c"}})
;=> "c"
0
votes

Your assumption that you can use a key as a lookup function is incorrect. You can use a keyword as a lookup function. In your example :a is a keyword. And so it can be used as a lookup function. But [:compound :mebaby] is not a keyword, that's a vector. Vectors can't be used as lookup functions.