Returns a map that consists of the rest of the maps conj-ed onto the first. If a key occurs in more than one map, the mapping from the latter (left-to-right) will be the mapping in the result.
;; `merge` can be used to support the setting of default values (merge {:foo "foo-default" :bar "bar-default"} {:foo "custom-value"}) ;;=> {:foo "custom-value" :bar "bar-default"} ;; This is useful when a function has a number of options ;; with default values. (defn baz [& options] (let [options (merge {:opt1 "default-1" :opt2 "default-2"} (first options))] options)) (baz {:opt1 "custom-1" :opt3 "custom-3"}) ;;=> {:opt3 "custom-3" :opt1 "custom-1 :opt2 "default-2"}
;; For recursively merging deeply-nested maps: (defn deep-merge [v & vs] (letfn [(rec-merge [v1 v2] (if (and (map? v1) (map? v2)) (merge-with deep-merge v1 v2) v2))] (if (some identity vs) (reduce #(rec-merge %1 %2) v vs) (last vs)))) (deep-merge {:a {:b true}} {:a {:b false}} {:a {:b nil}}) ;; {:a {:b nil}} (deep-merge {:a 1} nil) ;; nil ;; note that this isn't consistent with the regular merge function ;; Source: https://gist.github.com/danielpcox/c70a8aa2c36766200a95#gistcomment-2677502
;; latest comment under above gist provides another ;; simpler and more consistent version of deep-merge ;; Source: https://gist.github.com/danielpcox/c70a8aa2c36766200a95#gistcomment-2759497 (defn deep-merge [a & maps] (if (map? a) (apply merge-with deep-merge a maps) (apply merge-with deep-merge maps))) (deep-merge {:a {:b true}} {:a {:b false}} {:a {:b nil}}) ;; => {:a {:b nil}} (deep-merge {:a 1} nil) ;; => {:a 1}
;; Looking at the source code, merge starts with the ;; original collection and uses conj which adds elements ;; as is into the collection, so merge can be used ;; with more than just maps--i.e. using a vector returns a vector. (merge [:a "Whoa"] [:c "Crash Bandicoot"]) ;; => [:a "Whoa" [:c "Crash Bandicoot"]] (merge [:a "Whoa"] "Crash Bandicoot") ;; => [:a "Whoa" "Crash Bandicoot"]
;; in the source, merge uses `or` to substitute an empty map if given ;; `nil` for the first value. Since "or" also catches false, this works: (merge false {:a 1}) ;; => {:a 1} ;; On the other hand, this throws a ClassCastException: (merge true {:a 1}) ;; This probably shouldn't be relied on
;; This could be handy in certain situations. (defn reverse-merge "Same as `merge` but works in reverse order." [& maps] (apply merge (reverse maps))) (reverse-merge {:foo "FOO"} {:foo "---" :bar "BAR"} {:bar "---" :baz "BAZ"}) ;; => {:bar "BAR", :baz "BAZ", :foo "FOO"}
Returns a map that consists of the rest of the maps conj-ed onto the first. If a key occurs in mo...
keyval => key val Returns a new hash map with supplied mappings. If any keys are equal, they ar...
assoc[iate]. When applied to a map, returns a new map of the same (hashed/sorted) type, that con...
assoc
, conj
& merge
behave very differently for different data structures
If you are writing a function that can handle multiple kinds of collections, then your choice will make a big difference.
Treat merge as a maps-only function (its similar to conj for other collections).
My opinion:
assoc
- use when you are 'changing' existing key/value pairsconj
- use when you are 'adding' new key/value pairsmerge
- use when you are combining two or more maps