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.

Reply via email to