Clojure atom — Independent State · swap!, reset!, deref | Episode 25

0views
C
CelesteAI
Description
Clojure is an immutable language — and yet you still need state. An atom is how Clojure holds a single value that you can change over time, safely and without locks. In this episode we build two concrete examples with the same primitive: a hit counter (an integer) and a cache (a map). You'll see `(atom 0)`, `@deref`, `swap!` with a pure function, and `reset!` for blanket replacement — the full atom vocabulary. And because `swap!` is compare-and-set under the hood, your updates are atomic: every read is consistent with every write, even with concurrent callers. This kicks off Phase 5 — State and Concurrency — the part of Clojure where "immutable" stops meaning "you can't" and starts meaning "you can, safely". Student code: https://github.com/GoCelesteAI/clojure-for-beginners/tree/main/episode25 Every keystroke is shown on screen with generous pauses so you can follow along at your own pace. What You'll Learn: - `(atom 0)` — create a container for one value (any shape works) - `@counter` / `(deref counter)` — read the current value - `(swap! counter inc)` — apply a pure fn atomically; the result becomes the new value - `(swap! cache assoc :k v)` — same primitive, map shape, builds up key by key - `(swap! counter + 10)` — `swap!` accepts extra args the fn receives - `(reset! counter 0)` — replace the value unconditionally (use sparingly) - Compare-and-set — why `swap!`'s fn must be side-effect free - When to use atoms — independent state that doesn't need to coordinate with other state Timestamps: 0:00 - Intro 0:15 - Preview: one value, pure fn, atomic update 0:51 - The code — counter atom + cache atom 1:13 - Start the REPL, load the namespace 1:34 - @counter — deref reads the current value (zero) 1:44 - (hit!) — swap! with inc 1:54 - @counter — reads are consistent with writes 2:00 - (swap! counter + 10) — swap! with extra args 2:09 - (reset! counter 0) — blanket replacement 2:21 - @cache — same primitive, map shape 2:27 - (cache-set!) — swap! with assoc 2:45 - (cache-get) — simple get on the deref'd map 3:05 - Control-D 3:20 - clj -M:run — same primitives from main 3:30 - Recap 4:09 - What's next: Episode 26 Key Takeaways: 1. An atom is a container for one value. The value is immutable; the *atom* changes over time. 2. `@atom` reads the current value — cheap, consistent. 3. `(swap! atom f & args)` applies `f` to the current value plus args. The result becomes the new value — atomically. 4. `swap!`'s fn must be pure: Clojure may retry under contention (compare-and-set semantics). 5. `(reset! atom v)` replaces the whole value. Easier to reason about but loses the "evolve from current" property. 6. Same primitive, many shapes: a counter is an atom of `int`; a cache is an atom of `map`; a game's world is an atom of a deeply nested map. Phase 5 begins. Next up: `ref` and STM — when multiple pieces of state must stay in sync under concurrent updates. Taught by CelesteAI. Like and subscribe for more Clojure tutorials!
Back to tutorials

Duration

Added to Codegiz

April 20, 2026

📖 Read the articleOpen in YouTube