首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Clojure状态中的状态中的状态

Clojure状态中的状态中的状态
EN

Stack Overflow用户
提问于 2011-11-14 12:40:20
回答 3查看 2.3K关注 0票数 15

我很想听听这里的Clojure大师们对在层次结构中管理状态有什么建议。我发现我经常使用{:structures {:like {:this {:with {:many 'levels}} } } },如果我想通过在值(atom {:like (atom 'this)} )周围抛出原子来跟踪多个级别的状态变化,我发现自己认为这一定是错误的。通常情况下,在顶层只使用一个原子,并且在map中没有一个原子作为值,是不是更好?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2011-12-02 17:03:47

如果可能的话,不要在数据结构中使用嵌套原子。

最主要的原因是不变性是你的朋友。Clojure是一种基于不可变数据结构的函数式语言。大多数库都假定数据结构是不可变的。Clojure的STM假设使用不可变的数据结构来获得最好的并发性。不变性使您有机会在任何时刻拍摄整个状态的一致快照。操作不可变数据的纯函数很容易开发和测试。

如果你把原子放在你的数据结构中,那么你就失去了不可变性的所有优点,并且冒着让你的代码变得非常复杂的风险--如果一个数据结构包含了很多可变的组件,那么就很难对它进行推理了。

一些建议的替代方法:

  • 将您的整个数据结构放在一个引用或原子中。这可以是一个巨大的数据结构,没有任何问题-我曾经写过一个游戏,整个游戏地图都保存在一个原子中,没有任何difficulty.
  • Use,这些方法是为访问和更改嵌套的不可变数据结构而设计的:assoc-inget-inupdate-in等。
  • 使用递归函数来使导航数据结构更易于管理。如果您的结构中有一个节点具有相同“类型”的子节点,那么这通常是一个很好的提示,表明您应该使用某种形式的递归函数。
票数 14
EN

Stack Overflow用户

发布于 2011-11-14 15:40:28

您可以使用assoc-inget-inupdate-indissoc-in函数来处理嵌套结构。

它们非常方便,但我不知道它们是否能直接处理原子之类的东西。在最坏的情况下,你应该能够将它们嵌套到deref中,例如:

代码语言:javascript
复制
(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

您可以使用->使其更具可读性:

代码语言:javascript
复制
(-> @m
    (get-in [:like :this :nested])
    deref
    (get-in [:value]))
; => 5

关于嵌套的原子/ref/agent等,我认为这取决于你想要实现的目标。如果只有一个在顶部,并且更改是同步的,那么就更容易对事物进行推理。

另一方面,如果你不需要这种同步,你就是在浪费时间,而且你最好使用嵌套的原子/引用/代理。

底线是,我认为任何一种方式都不是“正确的方式”,它们都有自己的用途。

票数 12
EN

Stack Overflow用户

发布于 2011-11-14 13:31:54

我更喜欢在顶层使用一个原子,因为这将使事情变得非常简单,而且还表明数据表示一次n次由操作修改的状态。如果你把原子放在每个层次上,那么它就会变得太复杂,无法弄清楚到底发生了什么。另外,如果在你的例子中嵌套太深,那么我建议你坐下来仔细考虑你是否需要这样的结构,或者有更好的替代方案,因为这肯定会导致复杂性,直到嵌套的数据是递归的(即每一层都是相同的结构)。

票数 9
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8117404

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档