简体   繁体   中英

Set default values in sparse nested map in clojure

I've got a set of default values for a map, and I'd like to be able to take any stored map that doesn't have the values and apply the defaults.

ie if I've got the following inputs

(def defaults {:config {:tablet {:urls [] :enable false}}})
(def stored   {:config {:tablet {         :enable true }}})

I'd like to be able to create the following result.

              {:config {:tablet {:urls [] :enable true}}}

So the stored values are used when they exist, but the defaults are used when that key doesn't exist. I've tried merge , merge-with merge , merge-with concat , merge-with conj , and a few other incantations but none seem quite to work. One that does work is, if you know the max depth of nesting, (merge-with (partial merge-with ... (partial merge-with merge) ... )) but that's pretty hacky. Seems like there should be a simpler solution since this seems like it would be not-uncommon in Clojuresque code.

Something along the lines of the following should let you merge arbitrarily deeply nested maps:

(defn deep-merge [& ms]
    (apply merge-with
           (fn [& vs]
             (if (every? map? vs)
               (apply deep-merge vs)
               (last vs)))
           ms))

(deep-merge {:config {:tablet {:urls [] :enable false}}}
            {:config {:tablet {         :enable true }}})
; => {:config {:tablet {:urls [], :enable true}}}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM