clojure中的STM和alter

clojure中的STM和alter,clojure,stm,Clojure,Stm,我正在阅读《Clojure编程手册》。在解释alter和STM时,他们说,如果在alter期间,Clojure检测到事务外部对ref的更改,它将使用新值重新运行事务。如果是这样的话,我会设想您传入的更新函数需要是纯函数,但文档中没有指出这一点(在其他类似情况下也是如此) 那么我的假设正确吗?如果没有,STM如何重新应用该功能?如果这是正确的,是不是你不能依靠文档来告诉你什么时候可以产生副作用,什么时候不能?严格来说,它不一定是纯的,它只是必须是纯的。实际上,这基本上是一样的 此外,只有在STM之

我正在阅读《Clojure编程手册》。在解释
alter
和STM时,他们说,如果在alter期间,Clojure检测到事务外部对ref的更改,它将使用新值重新运行事务。如果是这样的话,我会设想您传入的更新函数需要是纯函数,但文档中没有指出这一点(在其他类似情况下也是如此)


那么我的假设正确吗?如果没有,STM如何重新应用该功能?如果这是正确的,是不是你不能依靠文档来告诉你什么时候可以产生副作用,什么时候不能?

严格来说,它不一定是纯的,它只是必须是纯的。实际上,这基本上是一样的

此外,只有在STM之外看到时,它才必须是幂等的:如果您产生的唯一副作用是写入其他ref或(我认为)发送给代理,则该操作将一直保持到您的事务成功为止

事实上,这些都不是必须的:只是,如果你的更新函数不是纯粹的,结果可能不是你所期望的

编辑:
dosync
的文档告诉您,正文中的任何表达式都可以执行多次。如果不运行
dosync
,就无法运行
alter
,因此看起来您需要的所有文档都在那里。您希望更改什么?

作为旁注:


如果您需要执行诸如登录STM事务之类的副作用,您可以向代理发送消息以执行非幂等部分。发送给代理的消息仅在事务完成时发送,并保证只发送一次

Clojure的要点是,在处理事务时没有副作用,因为它们是一致的,并且在更新共享值期间发现冲突时,函数将重新运行(我更喜欢重试),否则它将成功提交更改。
如果必须重试,它将读取更新后的值,因此没有副作用,您可能会发现问题是一个活锁,但它在Clojure的重试次数中受到限制。

我完全没有想到看dosyncs文档,我在看alter,回想起来有点傻。谢谢你的回答,完全是我想要的:)