liveBook · Manning

Commute

As explained in Clojure: The Essential Reference

commute is a Clojure function that records a ref update as order-independent when the update operations commute.

commute records an update to a ref inside a dosync transaction when concurrent update operations commute, allowing the operation’s ordering to be independent. It is useful for additive updates such as incrementing vote counts. section 14.4

Use commute when the update can be safely combined regardless of operation order:

  • Apply it through an updating function such as update, as in (commute votes update candidate inc). section 14.4
  • Keep the operation inside dosync, where refs coordinate as part of STM transactions. section 14.4
  • Do not perform I/O or other transaction-forbidden side effects in a function used by commute. section 14.4

Concurrent vote counting

Two futures repeatedly execute (commute votes update pref (fnil inc 0)) inside dosync. The resulting ref contains accumulated counts such as {"candidate-0" 50, "candidate-1" 153}, despite concurrent counters contributing updates. section 14.4

(def votes (ref {})) ; #1

(defn counter [poll votes] ; #2
  (future
    (dosync
      (doseq [pref poll]
        (commute votes update pref (fnil inc 0))))))

(defn generate-poll [& preference] ; #3
  (eduction
    (map-indexed #(repeat %2 (str "candidate-" %1)))
    cat
    preference))

(let [c1 (counter (generate-poll 40 64 19 82 11) votes) ; #4
      c2 (counter (generate-poll 10 89 23 75 22) votes)]
  [@c1 @c2]
  @votes)

;; {"candidate-0" 50 ; #5
;;  "candidate-1" 153
;;  "candidate-2" 42
;;  "candidate-3" 157
;;  "candidate-4" 33}

Browse the complete concurrent vote-counting example, including poll generation, futures, commute-based updates, and resulting counts. section 14.4

How Clojure: The Essential Reference covers it

How deep it goes
Defines the transactional update contract and demonstrates concurrent counters, but does not detail implementation internals.
Examples
Uses concurrent vote counters, candidate maps, honeypot detection, and an illegal I/O example.
What it assumes
Assumes familiarity with Clojure refs, dosync, transactions, and update functions.
What you can do after
Apply commute in dosync to accumulate safely across concurrent ref updates.
How it connects
Connects refs, dosync, STM, update, futures, and side-effect restrictions.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Clojure: The Essential Reference. The section links point to the parts of the book it draws on.