Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the Unified Update Model?

This Clojure code on GitHub refers to the Unified Update Model.

Could you explain how the fixing function works well with the Unified Update Model?

(defn fixing
  "A version of fix that fits better with the unified update model: instead of multiple clauses,
   additional args to the transform function are permitted. For example,
   (swap! my-atom fixing map? update-in [k] inc)"
  [x pred transform & args]
  (if ((as-fn pred) x)
    (apply (as-fn transform) x args)
    x))
like image 618
ardsrk Avatar asked Sep 03 '16 18:09

ardsrk


1 Answers

The unified update model is the API convention whereby objects of various reference types can be updated in a consistent way, albeit with specialized functions:

;; Atoms
(swap! the-atom f …)

;; Agents
(send the-agent f …)
(send-off the-agent f …)
;; send-via takes an additional initial argument, but otherwise
;; follows the same convention (and of course it's an exact match
;; when partially applied – (partial send-via some-executor))
(send-via executor the-agent f …)

;; Refs
(dosync
  (alter the-ref f …)
  (commute the-ref f…))

In each case f is the function that should be used to update the value held by the Atom / Agent / Ref, are additional arguments, if any (e.g. (swap! the-atom f 1 2 3)), and the result of the call is that the reference will atomically assume the value (f old-value …) – although exactly when that will happen with respect to the swap! / alter / send / … call depends on the reference type in question and the update function used.

Here's an example:

(def a (atom 0))
(swap! a - 5)
@a
;= -5

Vars are generally not meant to be used for the same purposes that one might use the above-mentioned reference types for, but they also have an update function with the same contract:

(alter-var-root #'the-var f …)

Finally, the update and update-in functions are worth mentioning in this connection; in effect, they extend the unified update model convention to values – now of course, values are immutable, so calling update or update-in does not result in any object being visibly changed, but the return value is produced similarly as the result of applying an update function to a preexisting value and possibly some extra arguments:

(update {:foo 1} :foo inc)
;= {:foo 2}

The fixing function quoted in the question works better than fix (defined in the same namespace) in the context of UUM update calls, because it can be passed multiple arguments in a way that meshes well with how UUM update functions like swap! work, whereas with fix you'd have to use an anonymous function:

;; the example from the docstring of fixing
(swap! my-atom fixing map? update-in [k] inc)

;; modified to use fix
(swap! my-atom fix map? #(update-in % [k] inc))
like image 66
Michał Marczyk Avatar answered Nov 11 '22 05:11

Michał Marczyk