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)
最后,update和update-in功能值得一提的在这方面; 实际上,它们将统一更新模型约定扩展为值 - 当然,值是不可变的,因此调用update或update-in不会导致任何对象被可见地更改,但返回值的生成与应用更新函数的结果类似一个预先存在的值,可能还有一些额外的参数:
(update {:foo 1} :foo inc)
;= {:foo 2}
Run Code Online (Sandbox Code Playgroud)
fixing在fixUUM更新调用的上下文中,问题中引用的函数比(在相同的命名空间中定义)更好,因为它可以以一种与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)