What's the difference between?
1.
(def x (ref 0))
(dosync
(commute x f))
2.
(def x (atom 0))
(swap! x f))
These two examples work equally
What's the difference between?
1.
(def x (ref 0))
(dosync
(commute x f))
2.
(def x (atom 0))
(swap! x f))
These two examples work equally
If you have only one ref and one atom, there actually is no big difference. I think you might learn something about the difference of atoms and refs.
commute
is a function which can be called in any place in the dosync
block. Clojure itself chooses when to execute an commute
inside this block.
Maybe I explan it with a small example:
(def x (ref 0))
(def y (ref 0))
(dosync (alter x inc)
(alter y dec))
alter
changes the value of a ref inside a dosync
block. Because refs are coordinated and synchronous, we need to place them inside this block. If here occurs an error while altering one of the refs, the whole block fails and your refs have the same value as they had before calling the alters.
The difference to commute is the following: If we have the following code block
(def x (ref 0))
(def y (ref 0))
(dosync (commute x inc)
(alter y dec))
If an error occurs here while changing the value of your refs, commute
is still called and it changes your ref. It does not care about the result of the alter
and even if the alter
fails, commute
does increment x.
Clojure can choose when to call commute, so it can be executed even if an error occurs.
The big difference to atoms is that atoms are not coordinated. If there are multiple swap!
on one atom, maybe just the first swap!
will be executed. One of my projects got stuck on this issue, I had to ensure that the first swap!
has terminated before the next swap!
is called.
So again: Think of what you really need. Do you need an atom or some refs? If you choose refs, you have the choice between alter
, which is executed at the position you want it to, or commute
where Clojure can decide when to call it (the call is then commutative).
If you choose an atom, you can only change one value while this atom is executed. If another call trys to swap!
the value, it is rejected.