Clojure 中的 Alter vs Commute:我做错了什么?
Alter vs Commute in Clojure: what am I doing wrong?
这里是 Clojure 新手,我正在阅读优秀的 "Clojure from the ground up" 帖子,并尝试了最后一个练习 in this post。
当我用commute
替换alter
时,总和不准确,但我不明白为什么。
(def work (ref (apply list (range 1e5))))
(def sum (ref 0))
(defn trans-alter [work sum]
(dosync
(if-let [n (first @work)]
(do
(alter work rest)
(alter sum + n)
(count @work))
0)))
(defn trans-commute [work sum]
(dosync
(if-let [n (first @work)]
(do
(commute work rest)
(commute sum + n)
(count @work))
0)))
(我跳过了设置期货和调用它们等的代码)
在这里使用 trans-alter
我得到了 4999950000
的总和(这是正确的预期值),而使用 trans-commute
我每次都得到不同的值,但高于预期(例如 4999998211
)。
我在这里错过了什么?提前致谢!
Commute 和 alter 本质上做同样的事情,尽管 commute 在保证正确性方面要宽松一些。运行
Alter 指示 STM 始终确保此代码 运行 一直通过,而它使用的任何引用都不会从其下方更改。
Commute 是一条指令,用于帮助 STM 决定何时需要中止 t运行saction,因为基础数据已从其下方更改。
如果 t运行saction 中的所有内容都是可交换的,那么让 t运行saction 完成是可以的即使某些数据已更改。在你的情况下,两个 t运行saction 都可以:
- 抢到第一个号码
- 从工作中删除相同的号码
- 将相同的数字添加到结果
- 然后使用
commute
指示 STM 这是可以的,它应该继续并提交 t运行saction 无论如何...
- 答错了。
简而言之,您要执行的工作实际上并不是交换操作。具体来说,从列表中删除一个项目是不可交换的。如果您将任何通勤更改为 alter,那么第 4 步会将其中一个踢出并且只允许其中一个完成。被踢出的将是 re-run 新数据,最终会得出正确的结果。
这里是 Clojure 新手,我正在阅读优秀的 "Clojure from the ground up" 帖子,并尝试了最后一个练习 in this post。
当我用commute
替换alter
时,总和不准确,但我不明白为什么。
(def work (ref (apply list (range 1e5))))
(def sum (ref 0))
(defn trans-alter [work sum]
(dosync
(if-let [n (first @work)]
(do
(alter work rest)
(alter sum + n)
(count @work))
0)))
(defn trans-commute [work sum]
(dosync
(if-let [n (first @work)]
(do
(commute work rest)
(commute sum + n)
(count @work))
0)))
(我跳过了设置期货和调用它们等的代码)
在这里使用 trans-alter
我得到了 4999950000
的总和(这是正确的预期值),而使用 trans-commute
我每次都得到不同的值,但高于预期(例如 4999998211
)。
我在这里错过了什么?提前致谢!
Commute 和 alter 本质上做同样的事情,尽管 commute 在保证正确性方面要宽松一些。运行
Alter 指示 STM 始终确保此代码 运行 一直通过,而它使用的任何引用都不会从其下方更改。
Commute 是一条指令,用于帮助 STM 决定何时需要中止 t运行saction,因为基础数据已从其下方更改。
如果 t运行saction 中的所有内容都是可交换的,那么让 t运行saction 完成是可以的即使某些数据已更改。在你的情况下,两个 t运行saction 都可以:
- 抢到第一个号码
- 从工作中删除相同的号码
- 将相同的数字添加到结果
- 然后使用
commute
指示 STM 这是可以的,它应该继续并提交 t运行saction 无论如何... - 答错了。
简而言之,您要执行的工作实际上并不是交换操作。具体来说,从列表中删除一个项目是不可交换的。如果您将任何通勤更改为 alter,那么第 4 步会将其中一个踢出并且只允许其中一个完成。被踢出的将是 re-run 新数据,最终会得出正确的结果。