I wonder how I would spec a function, that has a parameter, that hold a map in an atom.
(defn do-something [a]
(prn (vals @a)))
This those obviously not work:
(s/fdef do-something
:args (s/cat :a map?))
How would I spec that a
is a reference to map?
Atoms are a data type in Clojure that provide a way to manage shared, synchronous, independent state. An atom is just like any reference type in any other programming language. The primary use of an atom is to hold Clojure's immutable datastructures. The value held by an atom is changed with the swap!
spec is a Clojure library to describe the structure of data and functions. Specs can be used to validate data, conform (destructure) data, explain invalid data, generate examples that conform to the specs, and automatically use generative testing to test functions.
Don't. clojure.spec is about specifying the structure of data and atoms are state, not data. Not every function necessarily needs to have (or check) a spec.
My general advice for dealing with stateful data is to:
With some care, you can often reduce the number of functions that take or return atoms to 0 (by closing over the atom in the place where it's managed), which is imho a worthy goal.
You don't. For one reason, it wouldn't be thread-safe. If you did somehow spec that a atom contained a map, it could change to an integer in the time it takes you to check the atom, and continue with your function.
One option, however, is to provide a validator to the atom. You could easily use partial to do this: (set-validator! my-atom (partial s/valid? :my-spec))
. Now the atom will fail to update unless the value conforms to :my-spec.
Another option is to add validation logic to all the functions that update the atom. Which of these two approaches works best depends on the application.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With