(assoc-in m [k & ks] v)
Associates a value in a nested associative structure, where ks is a sequence of keys and v is the new value and returns a new nested structure. If any levels do not exist, hash-maps will be created.
(def users [{:name "James" :age 26} {:name "John" :age 43}])
;; update the age of the second (index 1) user
(assoc-in users [1 :age] 44)
;;=> [{:name "James", :age 26} {:name "John", :age 44}]
;; insert the password of the second (index 1) user
(assoc-in users [1 :password] "nhoJ")
;;=> [{:name "James", :age 26} {:password "nhoJ", :name "John", :age 43}]
;; create a third (index 2) user
;; Also (assoc m 2 {...}) or (conj m {...})
(assoc-in users [2] {:name "Jack" :age 19})
;;=> [{:name "James", :age 26} {:name "John", :age 43} {:name "Jack", :age 19}]
;; From http://clojure-examples.appspot.com/clojure.core/assoc-in
;; can be used to update a mutable item.
(def ppl (atom {"persons" {"joe" {:age 1}}}))
(swap! ppl assoc-in ["persons" "bob"] {:age 11})
@ppl
;;=> {"persons" {"joe" {:age 1}, "bob" {:age 11}}}
;; be careful with that empty path sequence, it's seldom what you want
(assoc-in {} [] {:k :v})
;;=> {nil {:k :v}}
;; In general, you find that for a non-empty path
;; (get-in (assoc-in m path v) path)
;; is equal to v.
;; Surprisingly this does not hold true in case of an empty path.
;; another example of updating a mutable item.
;; this time the first key is to a map and the second to a vector.
(def foo (atom {:users [{:a "a"} {:b "b"}]}))
(swap! foo assoc-in [:users 2] {:c "c"})
;;=> {:users [{:a "a"} {:b "b"} {:c "c"}]}
;; assoc-in into a nested map structure
(def foo {:user {:bar "baz"}})
(assoc-in foo [:user :id] "some-id")
;;=> {:user {:bar "baz", :id "some-id"}}
(assoc-in {} [:cookie :monster :vocals] "Finntroll")
; => {:cookie {:monster {:vocals "Finntroll"}}}
(get-in {:cookie {:monster {:vocals "Finntroll"}}} [:cookie :monster])
; => {:vocals "Finntroll"}
(assoc-in {} [1 :connections 4] 2)
; => {1 {:connections {4 2}}}
;; from http://www.braveclojure.com/functional-programming/
;; assoc-in can be used on vectors too
(def row 0)
(def col 0)
(assoc-in [[1 1 1]
[1 1 1]
[1 1 1]] [row col] 0)
; => [[0 1 1][1 1 1][1 1 1]]
(get-in [[0 1 1]
[1 1 1]
[1 1 1]] [row col])
; => 0
; Playing around with assoc-in
(assoc-in {:person {:name "Mike"}} [:person :name] "Violet")
; => {:person {:name "Violet"}}
(assoc-in {:person {:name "Mike"}} [:person] "Violet")
; => {:person "Violet"}
(assoc-in [{:person {:name "Mike"}}] [0 :person :name] "Violet")
; => [{:person {:name "Violet"}}]
(assoc-in [{:person {:name ["Mike"]}}] [0 :person :name 1] "Smith")
; => [{:person {:name ["Mike" "Smith"]}}]
(assoc-in [{:person {:name ["Mike"]}}] [0 :person :name 2] "Smith")
; => IndexOutOfBoundsException