Hen*_*gon 14 state clojure hierarchy
我很想听听Clojure大师们在层次结构中管理状态的建议.我发现我经常使用{:structures {:like {:this {:with {:many 'levels}} } } }
,如果我想跟踪多个级别的状态变化,通过抛出值的原子(atom {:like (atom 'this)} )
,我发现自己认为这一定是错的.通常最好只在顶层使用一个原子,并且在地图中没有任何值作为值?
mik*_*era 13
如果可能的话,不要在数据结构中使用嵌套原子.
主要原因是不变性是你的朋友.Clojure是一种在不可变数据结构上蓬勃发展的函数式语言.大多数库都采用不可变的数据结构.Clojure的STM采用不可变数据结构来获得最佳的并发性.不变性使您有机会在任何一个瞬间拍摄整个州的一致快照.对不可变数据进行操作的纯函数易于开发和测试.
如果将原子放入数据结构中,那么就会失去不可变性的所有优点,并且会使代码变得非常复杂 - 如果数据结构包含大量可变组件,则要更加难以推理数据结构.
一些建议的替代方法:
iva*_*ant 12
您可以使用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
Run Code Online (Sandbox Code Playgroud)
您可以使用它->
来使其更具可读性:
(-> @m
(get-in [:like :this :nested])
deref
(get-in [:value]))
; => 5
Run Code Online (Sandbox Code Playgroud)
关于嵌套的原子/参考/代理等,我认为这取决于你想要实现的目标.理解事物当然更容易,如果只有一个在顶部,并且变化是同步的.
另一方面,如果你不需要这种同步,你就会浪费时间去做,而你最好使用嵌套的atoms/refs/agents.
最重要的是,我认为无论哪种方式都是"正确的方式",它们都有其用途.
我更喜欢在顶级使用一个原子,因为这会使事情变得非常简单,并且还表明数据代表一个状态,该状态由操作立即修改.如果你把原子放在每个层次上,那么它就会变得太复杂而无法弄清楚发生了什么.另外,如果你的情况下嵌套方式太深,我建议你坐下来仔细考虑是否需要这样的结构,或者可以有更好的替代方案,因为这肯定会导致复杂性,直到嵌套数据递归为止(即每个级别的结构相同)