I wrote a function to get the old value of an atom while putting a new value, all in one atomic operation:
(defn get-and-reset! [at newval] "Resets atom to newval and returns the old value. Atomic." (let [tmp (atom [])] (swap! at #(do (reset! tmp %) newval)) @tmp)) The documentation says the swap! function shouldn't have side effects because it can be called multiple times. That alone doesn't seem like a problem since tmp never leaves the function and it's the last value that it gets reset! to that matters. The function seems to work but I haven't tested it thoroughly with multiple threads, etc. Is this local side-effect a safe exception to the documentation, or am I missing some other subtle problem?
(let [old @at] (reset! at newval) oldval).. or, did I miss your intent?get-and-reset!. If they both deref the atom before each other canreset!, they would both return the same value, meaning one of the values that the atom had would never be returned.reset!, but return the old value instead. You might want to look at: dev.clojure.org/jira/browse/CLJ-1454 and dev.clojure.org/jira/browse/CLJ-1599.swap!would be used, but if we imagine that instead of that, we did(reset! at (inc oldval))then of course we need to synchronize. But we essentially "throw away" old value, so the moment it is read seems rather unimportant. In many use cases my suggestion would be perfectly valid, but for some maybe it would not, if some order of returned old values was important