I think functions like this become pretty clear if you pull out 'unfold'
and 'fold' utilites, like:
https://github.com/Prismatic/plumbing/blob/master/src/plumbing/map.clj#L42
Their 'flatten' generates a seq [path value] pairs, and 'unflatten' turns
that back into a map. With these, you can write your functions
(defn to-map [kv-seq] (into {} kv-seq)) ;; utility
(defn flatten-map [m kf vf]
(->> m
flatten
(map (fn [[ks v]] [(kf ks) (vf v)]))
to-map))
(defn mapf [m f & args]
(->> m
flatten
(map (fn [[ks v]] [ks (apply f v args)]))
unflatten))
(defn deep-merge-with [f & ms]
(->> ms
(map flatten)
(map to-map)
(reduce (fn [res m] (merge-with f res m))) ;; could use 'partial'
unflatten))
(defn deep-merge [a b]
(deep-merge-with (fn [x y] y) a b))
;; bonus: also useful for fns that don't return a map
(defn max-depth [m]
(->> m
flatten
(map (comp count first))
(apply max 0)))
I think these fns are the same as yours. I have not tested them in any
significant way, though. I am also not thinking about performance.
Hope that helps,
Leif
On Wednesday, October 2, 2013 1:05:30 AM UTC-4, Yoshinori Kohyama wrote:
>
> Hi clojurians.
>
> I have functions for nested maps.
> They obviously have a same structure.
> Does anyone teach me a way to generalize them with a macro, a function or
> an existing API?
>
> (defn flatten-map [m kf vf]
> (into {}
> ((fn g [kv n]
> (if (map? n)
> (apply concat
> (keep (fn [[k v]] (g (conj kv k) v)) n))
> (if-let [kfkv (kf kv)]
> (if-let [vfn (vf n)]
> [[kfkv vfn]]))))
> [] m)))
>
> (defn deep-merge [a b]
> (reduce (fn [a [kv n]] (assoc-in a kv n))
> a
> ((fn g [kv n]
> (if (map? n)
> (apply concat
> (map (fn [[k v]] (g (conj kv k) v)) n))
> [[kv n]]))
> [] b)))
>
> (defn mapf [m f & args]
> (reduce (fn [a [kv n]] (assoc-in a kv n))
> {}
> ((fn g [kv n]
> (if (map? n)
> (apply concat
> (keep (fn [[k v]] (g (conj kv k) v)) n))
> (if-let [fna (apply f n args)]
> [[kv fna]])))
> [] m)))
>
> https://gist.github.com/kohyama/6789280 (with examples as tests)
>
> Regards,
> Yoshinori Kohyama
>
--
--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to [email protected]
Note that posts from new members are moderated - please be patient with your
first post.
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
---
You received this message because you are subscribed to the Google Groups
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.