我很想听听这里的Clojure大师们对在层次结构中管理状态有什么建议。我发现我经常使用{:structures {:like {:this {:with {:many 'levels}} } } },如果我想通过在值(atom {:like (atom 'this)} )周围抛出原子来跟踪多个级别的状态变化,我发现自己认为这一定是错误的。通常情况下,在顶层只使用一个原子,并且在map中没有一个原子作为值,是不是更好?
发布于 2011-12-02 17:03:47
如果可能的话,不要在数据结构中使用嵌套原子。
最主要的原因是不变性是你的朋友。Clojure是一种基于不可变数据结构的函数式语言。大多数库都假定数据结构是不可变的。Clojure的STM假设使用不可变的数据结构来获得最好的并发性。不变性使您有机会在任何时刻拍摄整个状态的一致快照。操作不可变数据的纯函数很容易开发和测试。
如果你把原子放在你的数据结构中,那么你就失去了不可变性的所有优点,并且冒着让你的代码变得非常复杂的风险--如果一个数据结构包含了很多可变的组件,那么就很难对它进行推理了。
一些建议的替代方法:
发布于 2011-11-14 15:40:28
您可以使用assoc-in、get-in、update-in和dissoc-in函数来处理嵌套结构。
它们非常方便,但我不知道它们是否能直接处理原子之类的东西。在最坏的情况下,你应该能够将它们嵌套到deref中,例如:
(def m (atom {:like {:this {:nested (atom {:value 5})}}}))
@(get-in @m [:like :this :nested])
; => {:value 5}
(get-in @(get-in @m [:like :this :nested]) [:value])
; => 5您可以使用->使其更具可读性:
(-> @m
(get-in [:like :this :nested])
deref
(get-in [:value]))
; => 5关于嵌套的原子/ref/agent等,我认为这取决于你想要实现的目标。如果只有一个在顶部,并且更改是同步的,那么就更容易对事物进行推理。
另一方面,如果你不需要这种同步,你就是在浪费时间,而且你最好使用嵌套的原子/引用/代理。
底线是,我认为任何一种方式都不是“正确的方式”,它们都有自己的用途。
发布于 2011-11-14 13:31:54
我更喜欢在顶层使用一个原子,因为这将使事情变得非常简单,而且还表明数据表示一次n次由操作修改的状态。如果你把原子放在每个层次上,那么它就会变得太复杂,无法弄清楚到底发生了什么。另外,如果在你的例子中嵌套太深,那么我建议你坐下来仔细考虑你是否需要这样的结构,或者有更好的替代方案,因为这肯定会导致复杂性,直到嵌套的数据是递归的(即每一层都是相同的结构)。
https://stackoverflow.com/questions/8117404
复制相似问题