Atoms
The function passed to swap! may run multiple times under contention, so keep it pure (no side effects).
(def counter (atom 0))
@counter ; 0
(swap! counter inc) ; 1: applies a pure function atomically (retries on contention)
(swap! counter + 10) ; 11
(reset! counter 0) ; set directly
(compare-and-set! counter 0 5) ; true
(swap-vals! counter inc) ; [5 6]: old and new values
(reset-vals! counter 100) ; [6 100]
;; Map state
(def app-state (atom {:users {} :next-id 1}))
(defn add-user! [name]
(swap! app-state
(fn [{:keys [next-id] :as state}]
(-> state
(assoc-in [:users next-id] {:id next-id :name name})
(update :next-id inc)))))
(add-user! "Ana")
(add-user! "Bo")
(get-in @app-state [:users 2 :name]) ; "Bo"
;; Validators and watches
(def age (atom 30 :validator #(<= 0 % 150)))
;; (reset! age -1) ; throws IllegalStateException: Invalid reference state
(add-watch counter :logger
(fn [key ref old new] (println "counter:" old "->" new)))
(swap! counter inc) ; prints "counter: 100 -> 101"
(remove-watch counter :logger)