Reputation: 4643
I came across a thing I needed today where I wanted to progressively associate entries in a map, each based on the results of the previous one(s). Here's what I did:
(defn -Y [v k f] (assoc v k (f v)))
(defn build-map [a-map]
(-> a-map
(-Y :x #(reduce + (:values %) ) )
(-Y :y #(/ (:x %) 100) )
(-Y :z #(* (:y %) 10000000) )
)
)
(build-map {:values (range 8)})
I'd welcome your thoughts on a) is it a good thing ? b) is there an existing way to do it that I haven't seen ? (I don't know the API well)
Upvotes: 3
Views: 152
Reputation: 14506
I think the answer by Ankur is a good improvement on your original design.
I just wanted to mention that it's not always necessary to overcomplicate things. If you compute all the additional map entries in the same function anyways, this simple approach is much more readable, in my opinion:
(defn build-map [a-map]
(let [x (reduce + (:values a-map))
y (/ x 100)
z (* y 10000000)]
(merge a-map {:x x :y y :z z})))
Upvotes: 10
Reputation: 33657
So you got a map that goes through some transformations and you end up with a final map. Your implementation looks fine to me except that -Y
isn't doing much of thing and it may not be required as a separate function.
You can do all this using just reduce
function, something like:
(def operations [ [:x #(reduce + (:values %))]
[:y #(/ (:x %) 100)]
[:z #(* (:y %) 10000000)]
])
(defn build-map [a-map]
(reduce (fn [s [k f]] (assoc s k (f s) ) ) a-map operations)
)
(build-map {:values (range 8)})
Upvotes: 7