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 clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com 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 clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/groups/opt_out.