user1172274
user1172274

Reputation: 111

Can the alter be replaced with commute in the following Clojure code?

(def alice-height
  (ref 3))

(def right-hand-bites
  (ref 10))

(defn eat-from-right-hand []
  (dosync
    (when (pos? @right-hand-bites)
      (alter right-hand-bites dec)
      (alter alice-height #(+ % 24)))))

This code is from the book Living Clojure. In the book, the author also gave an example with alter replaced by commute. I'm wondering with the pos? test at the beginning, can we really do this replacement?

Upvotes: 4

Views: 121

Answers (1)

glts
glts

Reputation: 22684

No, replacing alter with commute when decrementing right-hand-bites is not correct.

The intention of the conditional is apparently to prevent right-hand-bites from becoming negative. The decrement is only valid under the assumption that right-hand-bites won’t change until the end of the transaction. While, like alter, commute has its own snapshot view of the ref world, it will re-read and re-apply the commute function to the ref at commit time, and that would be a mistake in this program.

So, with commute it is possible to commit a negative value to right-hand-bites.

Either stick with alter, or use ensure instead of @ (though that makes the whole commute exercise rather pointless).

Upvotes: 1

Related Questions