Clojure

Add deref-swap! and deref-reset! (swap! and reset! that return prior value)

Details

  • Type: Enhancement Enhancement
  • Status: Open Open
  • Priority: Critical Critical
  • Resolution: Unresolved
  • Affects Version/s: None
  • Fix Version/s: None
  • Component/s: None
  • Labels:
  • Patch:
    Code and Test
  • Approval:
    Prescreened

Description

Sometimes, when swapping or resetting an atom, it's desirable to know the value before the update. The existing swap! and reset! functions return the new value instead. Currently, the only option is to roll your own using a loop and compare-and-set!

Example use cases:

  • When an atom contains a PersistentQueue and you want to atomically remove the head of the queue and process it: if you run (swap! q pop), you have lost the reference to the old head of the list so you can't process it.
  • Want to check if an operation has occurred before by using atom as a flag (this can be achieved with compare-and-set! but reads a little easier this way).
    (def has-run-once (atom false))
    ...
    (when-not (get-and-set! has-run-once true)
    (do something))
  • Want to use an atom similarly to a java.util.concurrent.LinkedTransferQueue, for the case of pairing up adds by writers and drainTo y readers:
    Thread 1: (swap! atm conj item1)
    Thread 2: (swap! atm conj item2)
    Thread 3: (let [new-vals (get-and-set! atm [])] 
    (do-something new-vals))

Approach:

  • Extends clojure.lang.IAtom with derefReset and derefSwap with the exact same arities as their original variants, .reset and .swap. The deref-methods returns the old (deref-ed) value of the atom after a successful mutation of the atom.
  • Added clojure.core/deref-reset! - just like reset! it unconditionally changes values of atoms but returns
    the old atom value. Based on Steven Yi's get-and-set! in ticket CLJ-1599, patch named get-and-set.diff
  • Added clojure.core/deref-swap! - just like swap! but returns the old atom value.

Patch: deref-swap-deref-reset-with-IAtomDeref-and-tests.diff

Activity

Alex Miller made changes -
Field Original Value New Value
Labels atom
Approval Triaged [ 10120 ]
Alex Miller made changes -
Priority Minor [ 4 ] Major [ 3 ]
Alex Miller made changes -
Summary Companion to swap! which returns the old value Add a swap! that returns old value
Alex Miller made changes -
Priority Major [ 3 ] Critical [ 2 ]
Alex Miller made changes -
Summary Add a swap! that returns old value Add deref-swap! (swap! that returns prior value)
Description Sometimes, when mutating an atom, it's desirable to know what the value _before_ the swap happened. The existing swap! function returns the new value, so is unsuitable for this use case. Currently, the only option is to roll your own using a loop and compare-and-set!

An example of this would be where the atom contains a PersistentQueue and you want to atomically remove the head of the queue and process it: if you run {{(swap! a pop)}}, you have lost the reference to the old head of the list so you can't process it.

It would be good to have a new function swap-returning-old! which returned the old value instead of the new.
Sometimes, when mutating an atom, it's desirable to know what the value _before_ the swap happened. The existing swap! function returns the new value, so is unsuitable for this use case. Currently, the only option is to roll your own using a loop and compare-and-set!

An example of this would be where the atom contains a PersistentQueue and you want to atomically remove the head of the queue and process it: if you run {{(swap! a pop)}}, you have lost the reference to the old head of the list so you can't process it.

It would be good to have a new function deref-swap! which returned the old value instead of the new.
Linus Ericsson made changes -
Alex Miller made changes -
Summary Add deref-swap! (swap! that returns prior value) Add deref-swap! and deref-reset! (swap! and reset! that return prior value)
Alex Miller made changes -
Description Sometimes, when mutating an atom, it's desirable to know what the value _before_ the swap happened. The existing swap! function returns the new value, so is unsuitable for this use case. Currently, the only option is to roll your own using a loop and compare-and-set!

An example of this would be where the atom contains a PersistentQueue and you want to atomically remove the head of the queue and process it: if you run {{(swap! a pop)}}, you have lost the reference to the old head of the list so you can't process it.

It would be good to have a new function deref-swap! which returned the old value instead of the new.
Sometimes, when mutating an atom, it's desirable to know what the value _before_ the swap happened. The existing swap! function returns the new value, so is unsuitable for this use case. Currently, the only option is to roll your own using a loop and compare-and-set!

An example of this would be where the atom contains a PersistentQueue and you want to atomically remove the head of the queue and process it: if you run {{(swap! a pop)}}, you have lost the reference to the old head of the list so you can't process it.

Approach:

- Extends {{clojure.lang.IAtom}} with {{derefReset}} and {{derefSwap}} with the exact same arities as their original variants, {{.reset}} and {{.swap}}. The deref-methods returns the old (deref-ed) value of the atom after
a successful mutation of the atom.
- Added {{clojure.core/deref-reset!}} - just like reset! it unconditionally changes values of atoms but returns
the old atom value. Based on Steven Yi's get-and-set! in ticket CLJ-1599,
patch named get-and-set.diff
- Added {{clojure.core/deref-swap!}} - just like swap! but returns the old atom value.

*Patch:* deref-swap-deref-reset-extending-IAtom.diff
Patch Code [ 10001 ]
Alex Miller made changes -
Description Sometimes, when mutating an atom, it's desirable to know what the value _before_ the swap happened. The existing swap! function returns the new value, so is unsuitable for this use case. Currently, the only option is to roll your own using a loop and compare-and-set!

An example of this would be where the atom contains a PersistentQueue and you want to atomically remove the head of the queue and process it: if you run {{(swap! a pop)}}, you have lost the reference to the old head of the list so you can't process it.

Approach:

- Extends {{clojure.lang.IAtom}} with {{derefReset}} and {{derefSwap}} with the exact same arities as their original variants, {{.reset}} and {{.swap}}. The deref-methods returns the old (deref-ed) value of the atom after
a successful mutation of the atom.
- Added {{clojure.core/deref-reset!}} - just like reset! it unconditionally changes values of atoms but returns
the old atom value. Based on Steven Yi's get-and-set! in ticket CLJ-1599,
patch named get-and-set.diff
- Added {{clojure.core/deref-swap!}} - just like swap! but returns the old atom value.

*Patch:* deref-swap-deref-reset-extending-IAtom.diff
Sometimes, when mutating an atom, it's desirable to know what the value _before_ the swap happened. The existing swap! function returns the new value, so is unsuitable for this use case. Currently, the only option is to roll your own using a loop and compare-and-set!

An example of this would be where the atom contains a PersistentQueue and you want to atomically remove the head of the queue and process it: if you run {{(swap! a pop)}}, you have lost the reference to the old head of the list so you can't process it.

Approach:

- Extends {{clojure.lang.IAtom}} with {{derefReset}} and {{derefSwap}} with the exact same arities as their original variants, {{.reset}} and {{.swap}}. The deref-methods returns the old (deref-ed) value of the atom after a successful mutation of the atom.
- Added {{clojure.core/deref-reset!}} - just like reset! it unconditionally changes values of atoms but returns
the old atom value. Based on Steven Yi's get-and-set! in ticket CLJ-1599, patch named get-and-set.diff
- Added {{clojure.core/deref-swap!}} - just like swap! but returns the old atom value.

*Patch:* deref-swap-deref-reset-extending-IAtom.diff
Alex Miller made changes -
Description Sometimes, when mutating an atom, it's desirable to know what the value _before_ the swap happened. The existing swap! function returns the new value, so is unsuitable for this use case. Currently, the only option is to roll your own using a loop and compare-and-set!

An example of this would be where the atom contains a PersistentQueue and you want to atomically remove the head of the queue and process it: if you run {{(swap! a pop)}}, you have lost the reference to the old head of the list so you can't process it.

Approach:

- Extends {{clojure.lang.IAtom}} with {{derefReset}} and {{derefSwap}} with the exact same arities as their original variants, {{.reset}} and {{.swap}}. The deref-methods returns the old (deref-ed) value of the atom after a successful mutation of the atom.
- Added {{clojure.core/deref-reset!}} - just like reset! it unconditionally changes values of atoms but returns
the old atom value. Based on Steven Yi's get-and-set! in ticket CLJ-1599, patch named get-and-set.diff
- Added {{clojure.core/deref-swap!}} - just like swap! but returns the old atom value.

*Patch:* deref-swap-deref-reset-extending-IAtom.diff
Sometimes, when swapping or resetting an atom, it's desirable to know the value _before_ the update. The existing {{swap!}} and {{reset!}} functions return the new value instead. Currently, the only option is to roll your own using a loop and compare-and-set!

Example use cases:

* When an atom contains a PersistentQueue and you want to atomically remove the head of the queue and process it: if you run {{(swap! q pop)}}, you have lost the reference to the old head of the list so you can't process it.
* Want to check if an operation has occurred before by using atom as a flag (this can be achieved with {{compare-and-set!}} but reads a little easier this way).
{code}
(def has-run-once (atom false))
...
(when-not (get-and-set! has-run-once true)
(do something))
{code}
* Want to use an atom similarly to a java.util.concurrent.LinkedTransferQueue, for the case of pairing up adds by writers and drainTo y readers:
{code}
Thread 1: (swap! atm conj item1)
Thread 2: (swap! atm conj item2)
Thread 3: (let [new-vals (get-and-set! atm [])]
(do-something new-vals))
{code}

Approach:

- Extends {{clojure.lang.IAtom}} with {{derefReset}} and {{derefSwap}} with the exact same arities as their original variants, {{.reset}} and {{.swap}}. The deref-methods returns the old (deref-ed) value of the atom after a successful mutation of the atom.
- Added {{clojure.core/deref-reset!}} - just like reset! it unconditionally changes values of atoms but returns
the old atom value. Based on Steven Yi's get-and-set! in ticket CLJ-1599, patch named get-and-set.diff
- Added {{clojure.core/deref-swap!}} - just like swap! but returns the old atom value.

*Patch:* deref-swap-deref-reset-extending-IAtom.diff
Linus Ericsson made changes -
Alex Miller made changes -
Description Sometimes, when swapping or resetting an atom, it's desirable to know the value _before_ the update. The existing {{swap!}} and {{reset!}} functions return the new value instead. Currently, the only option is to roll your own using a loop and compare-and-set!

Example use cases:

* When an atom contains a PersistentQueue and you want to atomically remove the head of the queue and process it: if you run {{(swap! q pop)}}, you have lost the reference to the old head of the list so you can't process it.
* Want to check if an operation has occurred before by using atom as a flag (this can be achieved with {{compare-and-set!}} but reads a little easier this way).
{code}
(def has-run-once (atom false))
...
(when-not (get-and-set! has-run-once true)
(do something))
{code}
* Want to use an atom similarly to a java.util.concurrent.LinkedTransferQueue, for the case of pairing up adds by writers and drainTo y readers:
{code}
Thread 1: (swap! atm conj item1)
Thread 2: (swap! atm conj item2)
Thread 3: (let [new-vals (get-and-set! atm [])]
(do-something new-vals))
{code}

Approach:

- Extends {{clojure.lang.IAtom}} with {{derefReset}} and {{derefSwap}} with the exact same arities as their original variants, {{.reset}} and {{.swap}}. The deref-methods returns the old (deref-ed) value of the atom after a successful mutation of the atom.
- Added {{clojure.core/deref-reset!}} - just like reset! it unconditionally changes values of atoms but returns
the old atom value. Based on Steven Yi's get-and-set! in ticket CLJ-1599, patch named get-and-set.diff
- Added {{clojure.core/deref-swap!}} - just like swap! but returns the old atom value.

*Patch:* deref-swap-deref-reset-extending-IAtom.diff
Sometimes, when swapping or resetting an atom, it's desirable to know the value _before_ the update. The existing {{swap!}} and {{reset!}} functions return the new value instead. Currently, the only option is to roll your own using a loop and compare-and-set!

Example use cases:

* When an atom contains a PersistentQueue and you want to atomically remove the head of the queue and process it: if you run {{(swap! q pop)}}, you have lost the reference to the old head of the list so you can't process it.
* Want to check if an operation has occurred before by using atom as a flag (this can be achieved with {{compare-and-set!}} but reads a little easier this way).
{code}
(def has-run-once (atom false))
...
(when-not (get-and-set! has-run-once true)
(do something))
{code}
* Want to use an atom similarly to a java.util.concurrent.LinkedTransferQueue, for the case of pairing up adds by writers and drainTo y readers:
{code}
Thread 1: (swap! atm conj item1)
Thread 2: (swap! atm conj item2)
Thread 3: (let [new-vals (get-and-set! atm [])]
(do-something new-vals))
{code}

Approach:

- Extends {{clojure.lang.IAtom}} with {{derefReset}} and {{derefSwap}} with the exact same arities as their original variants, {{.reset}} and {{.swap}}. The deref-methods returns the old (deref-ed) value of the atom after a successful mutation of the atom.
- Added {{clojure.core/deref-reset!}} - just like reset! it unconditionally changes values of atoms but returns
the old atom value. Based on Steven Yi's get-and-set! in ticket CLJ-1599, patch named get-and-set.diff
- Added {{clojure.core/deref-swap!}} - just like swap! but returns the old atom value.

*Patch:* deref-swap-deref-reset-with-IAtomDeref-and-tests.diff
Alex Miller made changes -
Approval Triaged [ 10120 ] Prescreened [ 10220 ]
Patch Code [ 10001 ] Code and Test [ 10002 ]

People

Vote (9)
Watch (5)

Dates

  • Created:
    Updated: