ClojureDocs

Nav

Namespaces

merge

clojure.core

Available since 1.0 (source)
  • (merge & maps)
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.
9 Examples
(merge {:a 1 :b 2 :c 3} {:b 9 :d 4})
;;=> {:d 4, :a 1, :b 9, :c 3}
(merge {:a 1} nil)   ;=> {:a 1}
(merge nil {:a 1})   ;=> {:a 1}
(merge nil nil)      ;=> nil
;; `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}
(merge {:x 1 :y 2} {:y 3 :z 4})
;; => {:x 1, :y 3, :z 4}
;; 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"}
See Also

Returns a map that consists of the rest of the maps conj-ed onto the first. If a key occurs in mo...

Added by Nebulus

keyval => key val Returns a new hash map with supplied mappings. If any keys are equal, they ar...

Added by boxie

assoc[iate]. When applied to a map, returns a new map of the same (hashed/sorted) type, that con...

Added by MicahElliott
2 Notes
    By , created 3.9 years ago, updated 3.9 years ago

    When to use assoc, conj, merge

    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 pairs
    • conj - use when you are 'adding' new key/value pairs
    • merge - use when you are combining two or more maps

    Ref : https://stackoverflow.com/a/3204346

    By , created 1.6 years ago

    Merge is more similar to concat than to conj IMO.