Reputation: 43
I have two maps, of the form:
(def h1 {:p1 {:x {:port :p1 :instr :x :qty 10}}})
(def h2 {:p1 {:y {:port :p1 :instr :y :qty 11}}})
When I merge them using
(apply (partial merge-with merge) [h1 h2])
I get the correct result:
-> {:p1 {:y {:port :p1, :qty 11, :instr :y}, :x {:port :p1, :qty 10, :instr :x}}
However, If I try reducing over a sequence of maps:
(reduce (fn [r m] apply (partial merge-with merge) r m) {} [h1 h2])
I get only the first map as a result:
-> {:p1 {:y {:port :p1, :qty 11, :instr :y}}}
I would expect the same result. What am I doing wrong?
Upvotes: 0
Views: 345
Reputation: 13473
You forgot to apply the apply
. In
(fn [r m] apply (partial merge-with merge) r m)
... the implicit do
in the fn
form performs a series of evaluations, returning the result of the last one. Ignoring side-effects (and there are none), the function is equivalent to
(fn [r m] m)
as you observed.
The reduce
takes the sequence of maps apart, so you don't need the apply
:
(reduce (fn [r m] (merge-with merge r m)) {} [h1 h2])
; {:p1
; {:y {:qty 11, :instr :y, :port :p1},
; :x {:qty 10, :instr :x, :port :p1}}}
If you are determined to use the same structure for the function, you have to do it this way:
(reduce (fn [r m] (apply (partial merge-with merge) [r m])) {} [h1 h2])
; {:p1
; {:y {:qty 11, :instr :y, :port :p1},
; :x {:qty 10, :instr :x, :port :p1}}}
apply
expects a sequence as its last argument, which it flattens into the trailing arguments to its first (function) argument.
Upvotes: 4