3

I am trying to write very simple code which shows different results between commute and alter in Clojure. Can someone create an example for this purpose?

Simpler is better to understand the difference.

BSMP
  • 4,596
  • 8
  • 33
  • 44
  • 1
    I don't think this is off-topic. It's asking for an example, but could just as well have been phrased like "What is the difference between commute and alter? Can anyone show me a function that demonstrates them behving differently?" – amalloy May 25 '16 at 01:59
  • 1
    I agree this is a valid and not obviously duplicate question. No easy answer comes to mind because they both always produce the same answer the just do so in different amounts of time, sometimes. – Arthur Ulfeldt May 25 '16 at 02:56

1 Answers1

1

Assuming commute is used correctly, there should be no difference in observed values of Refs, except insofar as using commute may help a transaction commit in a high-contention scenario where it would be difficult to do so with alter. Of course when this applies it is a rather significant difference in outcome…

It's easier to illustrate exactly how things differ using side effects. Here's a single-threaded example to illustrate the basic property that

  • alter will be called exactly once per "transaction try" (possibly only once),

  • commute will be called exactly once per "transaction try" (while commute will not cause them, it may be involved in retries if alter is used within the same dosync block) and then one final time to compute the committed value (so at least twice, though again, it will not cause retries on its own):


user=> (def r (ref nil))
#'user/r
user=> (dosync (alter r prn))
nil
nil
user=> (dosync (commute r prn))
nil
nil
nil

Using some Thread/sleeps and a handful of threads one could provoke more retries on the alter side while still observing two retries on the commute side, investigate the effect on Ref histories of using one or the other etc.

Michał Marczyk
  • 83,634
  • 13
  • 201
  • 212