有什么区别?
1
(def x (ref 0))
(dosync
(commute x f))
2
(def x (atom 0))
(swap! x f))
这两个例子同样适用
答案 0 :(得分:8)
如果你只有一个ref和一个原子,那么实际上没有太大区别。我想你可能会了解原子和参考的差异。
commute
是一个可以在dosync
块中的任何位置调用的函数。 Clojure本身选择何时在此块中执行commute
。
也许我用一个小例子解释它:
(def x (ref 0))
(def y (ref 0))
(dosync (alter x inc)
(alter y dec))
alter
更改dosync
块中ref的值。因为refs是协调和同步的,所以我们需要将它们放在这个块中。如果在更改其中一个ref时发生错误,则整个块都会失败并且您的refs具有与调用更改之前相同的值。
通勤的区别如下:如果我们有以下代码块
(def x (ref 0))
(def y (ref 0))
(dosync (commute x inc)
(alter y dec))
如果更改refs的值时此处发生错误,则仍会调用commute
并更改您的参考号。它不关心alter
的结果,即使alter
失败,commute
也会增加x。
Clojure可以选择何时调用commute,因此即使发生错误也可以执行。
与原子的最大区别在于原子不协调。如果一个原子上有多个swap!
,则可能只会执行第一个swap!
。我的一个项目遇到了这个问题,我必须确保在调用下一个swap!
之前第一个swap!
已经终止。
再次:想想你真正需要的东西。你需要一个原子或一些参考?如果你选择refs,你可以选择alter
,它在你想要它的位置执行,或commute
在哪里Clojure可以决定何时调用它(然后调用可交换)。
如果选择原子,则只能在执行此原子时更改一个值。如果另一个调用尝试swap!
该值,则会被拒绝。