如何查看clojure树的子集(哈希映射)的更改?

如何查看clojure树的子集(哈希映射)的更改?,clojure,Clojure,我希望观察Clojure散列映射(通过STM ref访问)的不同部分的变化,这形成了一个相当大的树,对于这些部分的变化,我希望调用一些注册的侦听器。在clojure中我如何做到这一点,因为我知道“添加监视”只适用于整个引用?因为clojure映射是不可变的,所以从概念角度看,树的单个部分并没有变化 不过,我可以看到几个不错的选择: 在整个树中添加一个表,但测试您感兴趣的特定部分是否已更改。这应该非常快速且易于测试(使用“get in”查找树的正确部分) 通过助手函数库对树进行所有更改,该库可以

我希望观察Clojure散列映射(通过STM ref访问)的不同部分的变化,这形成了一个相当大的树,对于这些部分的变化,我希望调用一些注册的侦听器。在clojure中我如何做到这一点,因为我知道“添加监视”只适用于整个引用?

因为clojure映射是不可变的,所以从概念角度看,树的单个部分并没有变化

不过,我可以看到几个不错的选择:

  • 在整个树中添加一个表,但测试您感兴趣的特定部分是否已更改。这应该非常快速且易于测试(使用“get in”查找树的正确部分)
  • 通过助手函数库对树进行所有更改,该库可以拦截您感兴趣的更改类型

    • Clojure映射是不可变的,这意味着它们也是线程安全的,这是一件好事。当您使用“assoc”或类似工具修改一个副本时,您正在创建一个新副本,其中存在更改的值。(请注意,不制作完整副本,而是使用高效的技术来创建副本。)

      我认为最好的方法可能是创建自己的数据结构,因为本质上您需要的是Java中的可变HashMap,而不是Clojure映射

      您可以围绕现有Java HashMap创建一个包装器,该包装器覆盖“put”和“putAll”方法,以便您可以检测正在更改的内容。如果HashMap中有一个HashMap,那么您将希望子HashMap也是您的新类型,以便可以检测任何级别的更改

      你可以称之为“WatchfulHashMap”。然后,您将需要创建此新HashMap的实例,如:

      (def m (ref (WatchfulHashMap.)))
      

      因此,可以从应用程序中的任何位置修改它的单个实例。

      我也会观察整个树,并使用get-in检查子集。您可以通过使用相同的?针对前一状态进行测试。差不多

      (defn change-tester [tree path]
        (let [orig (get-in tree path)]
          (fn [tree]
            (not (identical? (get-in tree path) orig)))))
      

      我不经常使用watchers,所以我不知道语法,但我相信您可以以某种方式附加上述函数。

      对不起,我的意思是,当树是ref时,如何监视部分更改。那么您是说clojure add watch仅对可变结构有效吗?不,它们对ref有效。如果使用“添加监视”方法,则似乎会强制为结构中的每个节点或一个区分结构新旧状态的监视“添加监视”。