Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Clojure - map or set with fixed value->key function?

I have quite a few records in my program that I end up putting in a map using one of their fields as key. For example

(defrecord Foo. [id afield anotherfield])

And then I'd add that to a map with the id as key. This is all perfectly doable, but a bit tedious, e.g. when adding a new instance of Foo to a map I need to extract the key first. I'm wondering if somewhere in clojure.core a data structure to do this already exist?

Basically I'd like to construct a set of Foo's by giving the set a value to key mapping function (i.e. :id) at construction time of the set, and then have that used when I want to add/find/remove/... a value.

So instead of:

(assoc my-map (:id a-foo) a-foo))

I could do, say:

(conj my-set a-foo)

And more interestingly, merge and merge-with support.

like image 857
Kurt Schelfthout Avatar asked Oct 11 '22 16:10

Kurt Schelfthout


1 Answers

Sounds like a simple case where you would want to use a function to eliminate the "tedious" part.

e.g.

(defn my-assoc [some-map some-record]
  (assoc some-map (:id some-record) some-record))

If you are doing this a lot and need different key functions, you might want to try a higher order function:

(defn my-assoc-builder [id-function]
  (fn [some-map some-record] 
    (assoc some-map (id-function some-record) some-record)))

(def my-assoc-by-id (my-assoc-builder :id))

Finally, note that you could do the same with a macro. However a useful general rule with macros is not to use them unless you really need them. Thus in this case, since it can be done easily with a function, I'd recommend sticking to functions.

like image 172
mikera Avatar answered Dec 20 '22 02:12

mikera