Skip to content

Instantly share code, notes, and snippets.

@pyrtsa
Created December 9, 2013 11:46
Show Gist options
  • Save pyrtsa/7871080 to your computer and use it in GitHub Desktop.
Save pyrtsa/7871080 to your computer and use it in GitHub Desktop.
Exchange atom value in Clojure. This function seems like a common enough pattern in Clojure it should find its place in the standard library.
(defn exchange!
"Atomically set the value of `atom` to `(apply f @atom args)`,
and return the value of `@atom` just before the assignment.
(See also: `clojure.core/swap!`)"
[atom f & args]
{:pre [(instance? clojure.lang.Atom atom)]}
(loop [oldval @atom]
(if (compare-and-set! atom oldval (apply f oldval args))
oldval
(recur @atom))))
;; Example:
(def tokens (atom #{10 20 30 40 50}))
(defn pop-token!
"Atomically `disj` an element in the set-valued atom,
returning the removed element."
[tokens-atom]
(first (exchange! tokens-atom
#(disj % (first %)))))
(future (pop-token! tokens))
(future (pop-token! tokens))
(future (pop-token! tokens))
(future (pop-token! tokens))
(pop-token! tokens)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment