什么是统一更新模型?

ard*_*srk 9 functional-programming clojure

GitHub上的这个Clojure代码指的是统一更新模型.

你能解释一下该fixing功能如何与统一更新模型配合良好吗?

(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))
Run Code Online (Sandbox Code Playgroud)

Mic*_*zyk 13

统一更新模型是API约定,其中各种引用类型的对象可以以一致的方式更新,尽管具有专门的功能:

;; 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…))
Run Code Online (Sandbox Code Playgroud)

在每种情况下f,应该用于更新Atom/Agent/Ref所持有的值的函数是附加参数,如果有的话(例如(swap! the-atom f 1 2 3)),并且调用的结果是引用将原子地假设该值(f old-value …)- 尽管确切地说,对于swap!/ alter/ send/ ...调用将发生什么时候取决于所讨论的引用类型和使用的更新函数.

这是一个例子:

(def a (atom 0))
(swap! a - 5)
@a
;= -5
Run Code Online (Sandbox Code Playgroud)

Vars通常不应用于与上述引用类型相同的目的,但它们也具有相同合同的更新函数:

(alter-var-root #'the-var f …)
Run Code Online (Sandbox Code Playgroud)

最后,updateupdate-in功能值得一提的在这方面; 实际上,它们将统一更新模型约定扩展为 - 当然,值是不可变的,因此调用updateupdate-in不会导致任何对象被可见地更改,但返回值的生成与应用更新函数的结果类似一个预先存在的值,可能还有一些额外的参数:

(update {:foo 1} :foo inc)
;= {:foo 2}
Run Code Online (Sandbox Code Playgroud)

fixingfixUUM更新调用的上下文中,问题中引用的函数比(在相同的命名空间中定义)更好,因为它可以以一种与UUM更新函数如swap!工作方式很好地融合的方式传递多个参数,而对于fix你来说必须使用匿名函数:

;; 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))
Run Code Online (Sandbox Code Playgroud)