Atoms are thread-safe containers for handling mutable state. In this chapter, we'll learn how to create and manipulate atoms. We'll also learn how to hook into an atom's lifecycle and execute side-effects.
All Clojure data structures are immutable but the real world might not be. Any useful application will have some state that changes over time. Clojure atoms are thread-safe constructs to accommodate mutable state.
In a true multi-threaded environment like JVM, atoms guarantee atomic updates across threads.
The examples in the chapter reside in the
first-project.atoms namespace. We suggest you create this file and follow along!
Create an atom#
New atoms can be created using the
atom function. The first argument is the initial value. This initial value can be anything: number, maps, functions, other atoms, etc.
atom function also takes two optional keyword arguments:
:validator: A predicate that's run before updating the value of the atom - if this returns false, the value is not updated
:metadata-map: Key-value pairs to hold the atom's metadata
Get an atom's current value#
A Clojure atom is an instance of a Clojure ref (reference). We'll not go into the details of refs, but you can think of them as a base class for an atom.
To get the current value of an atom (or any ref), we can use the
deref method. There are two ways to
the literal way using
the functional way using
Reset current value#
If you want to update the value without caring about the initial value, you can use the
reset! function. This function takes two arguments, the atom to reset and its new value.
The functions ending with an exclamation sign conventionally denote unsafe or impure operations. The exclamation sign is usually read as "bang".