Reputation: 8593
Is there a more idiomatic/readable way of writing a get-and-set function in Clojure than:
(def the-ref (ref {}))
(defn get-and-set [new-value]
(dosync
(let [old-value @the-ref]
(do
(ref-set the-ref new-value)
old-value))))
Upvotes: 3
Views: 187
Reputation: 91554
for the simple cases I tend to see this operation used directly instead of wrapped in a function:
hello.core> (dosync (some-work @the-ref) (ref-set the-ref 5))
5
In this case dosync
generally serves as the wrapper you are looking for. within the dosync
This is significant because dosync composes nicely with other transactions and makes the bounds of the transaction visible. If you are in a position where the wrapper function can completely encapsulate all the references to the ref then perhaps refs are not the best tool.
A typical use of refs could look more along these lines:
(dosync (some-work @the-ref @the-other-ref) (ref-set the-ref @the-other-ref))
The need to wrap it is rare because when ref's are used they typically are use in groups of more than one ref because coordinated changes are required by the problem at hand. In cases where their is just one value then atoms are more common.
Upvotes: 2