Idiomatic Clojure map (data) composition?



To be clear, I am talking about data structure maps {:like "this"}, not the function from lists to lists.

I’m looking for a function that “composes” two (or more) maps, where one map is used to transform the other:

(map-compose {:msg "Hello!" :count 99} {:msg :message :count :times})
;; => {:message "Hello!" :times 99}

This feels like a mix between just and comp.

  • Is there something like this in the standard library?
  • How would you approach this?



You’re in luck, this fn exists:

(clojure.set/rename-keys {:msg "Hello!" :count 99} 
                         {:msg :message :count :times})
;; => {:message "Hello!", :times 99}

It’s never made much sense to me that it’s in the clojure.set namespace, but that’s a minor quibble.



clojure.set/rename-keys is open, it doesn’t remove keys that are not found in the rename map. But I guess that’s okay, and aligned with Clojure’s semantics otherwise.

Note: (clojure.set/rename-keys m rename) is two-ary. If we want a variadic function, we can reduce straight over clojure.set/rename-keys:

(reduce clojure.set/rename-keys
        {:msg "Hello" :count 99}
        [rename-1 rename-2 rename-3])


If that’s a requirement then perhaps:

(let [kmap {:msg :message :count :times}]
  (-> {:msg "Hello!" :count 99}
      (rename-keys kmap)
      (select-keys (vals kmap))))

My preference with rename-keys is to :refer it from clojure.set so I can pretend it’s a core fn while working.