Reading — step 1 of 5
Learn
Clojure values are immutable. Atoms wrap a value in a mutable container with thread-safe updates.
(def counter (atom 0))
@counter ; deref — returns the current value: 0
(deref counter) ; same
(swap! counter inc) ; apply inc to current value: 1
(swap! counter + 5) ; apply + with extra arg: 6
(reset! counter 100) ; replace value: 100
swap! runs your function on the current value and CAS-loops if another thread changed the atom in the meantime. The function MUST be pure — it might be retried.
Updating maps in atoms:
(def state (atom {:users {} :count 0}))
(swap! state update :count inc)
(swap! state assoc-in [:users "alice"] {:age 30})
update and assoc-in are functional map operations — return new maps, leave the original intact. The atom holds the new map atomically.
Watchers trigger callbacks on change:
(add-watch counter :log
(fn [_key _atom old new]
(println "counter changed" old "->" new)))
Atoms are the workhorse for Clojure state. Use them for:
- Counters
- Caches
- Application configuration
- In-memory databases
For coordinated multi-cell updates, use refs + STM. For uncoordinated async updates, use agents. Most code only needs atoms.
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…