Kevin Behan
Kevin Behan

Reputation: 496

compound-key as lookup function in clojure

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.

Upvotes: 1

Views: 274

Answers (3)

at.
at.

Reputation: 52540

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.

Upvotes: 0

Davyzhu
Davyzhu

Reputation: 1109

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"

Upvotes: 0

Magos
Magos

Reputation: 3014

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.

Upvotes: 2

Related Questions