3
\$\begingroup\$

In an attempt to learn better functional programing I've attempted to convert some Python to idiomatic Clojure, but I'm not sure how well I did with parts of it.

One thing I found myself doing a lot was destructuring a map into a list and then converting it back into a map as in the following example that takes a map of products and ratings (e.g. {:m1 3.5 :m2 2}) and a multiplier and multiplies each rating by the multiplier and returns a map with the corresponding products.

(defn corrected-prod [person multiplyer]
  (into {} (map (fn [[k v]] [k (* v multiplyer)]) person)))

Is there a better way to do this? For context you can reference the code on GitHub.

\$\endgroup\$
2
\$\begingroup\$

Here's a few other ways you can go about it:

(defn map-vals [f a-map]
  (zipmap (keys a-map) (map f (vals a-map))))

(defn map-vals [f a-map]
  (reduce-kv #(assoc %1 %2 (f %3)) {} a-map))

or if you're set on transients/into

(defn map-vals [f a-map]
  (persistent! (reduce-kv #(assoc! %1 %2 (f %3)) (transient {}) a-map)))

This is a use case that could maybe stand to have a more elegant core tool, though. Or at least, I'm not the only one to miss it.
For what it's worth, the zipmap approach actually appears to perform best in my cursory testing and is pretty clear in its intent to change the values while keeping the keys as they were. If you're using a function literal it also means that fn doesn't have to take keys it's not going to do anything interesting with, which could make it a little clearer.

\$\endgroup\$
  • \$\begingroup\$ I like the (zipmap) I'll have to start using that. \$\endgroup\$ – mmbb Aug 17 '15 at 20:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.