[英]Clojure states within states within states
我很想聽聽Clojure大師們在層次結構中管理狀態的建議。 我發現我經常使用{:structures {:like {:this {:with {:many 'levels}} } } }
如果我想跟蹤多個級別的狀態變化,可以通過在值周圍拋出原子(atom {:like (atom 'this)} )
,我發現自己認為這一定是錯的。 通常最好只在頂層使用一個原子,並且在地圖中沒有任何值作為值?
如果可能的話,不要在數據結構中使用嵌套原子。
主要原因是不變性是你的朋友。 Clojure是一種在不可變數據結構上蓬勃發展的函數式語言。 大多數庫都采用不可變的數據結構。 Clojure的STM采用不可變數據結構來獲得最佳的並發性。 不變性使您有機會在任何一個瞬間拍攝整個州的一致快照。 對不可變數據進行操作的純函數易於開發和測試。
如果將原子放入數據結構中,那么就會失去不可變性的所有優點,並且會使代碼變得非常復雜 - 如果數據結構包含大量可變組件,則要更加難以推理數據結構。
一些建議的替代方法:
您可以使用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
關於嵌套的原子/參考/代理等,我認為這取決於你想要實現的目標。 如果只有其中一個位於頂部並且更改是同步的,那么推理事物肯定更容易。
另一方面,如果你不需要這種同步,你就會浪費時間去做,而你最好使用嵌套的atoms / refs / agents。
最重要的是,我認為無論哪種方式都是“正確的方式”,它們都有其用途。
我更喜歡在頂級使用一個原子,因為這會使事情變得非常簡單,並且還表明數據代表一個狀態,該狀態由操作立即修改。 如果你把原子放在每個層次上,那么它就會變得太復雜而無法弄清楚發生了什么。 另外,如果你的情況下嵌套方式太深,我建議你坐下來仔細考慮是否需要這樣的結構,或者可以有更好的替代方案,因為這肯定會導致復雜性,直到嵌套數據遞歸為止(即每個級別的結構相同)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.