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

时间:2011-01-02 18:37:48

标签: clojure

我想观察Clojure Hash映射的不同部分(通过STM ref访问)的变化,它形成了一个相当大的树,并且对于那些部分的更改,我想调用一些注册的侦听器。我怎么能在clojure中这样做,因为我理解“add-watch”仅适用于整个引用?

3 个答案:

答案 0 :(得分:2)

由于Clojure映射是不可变的,因此从概念的角度来看,实际上并没有对树的单个部分进行更改。

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

  • 将监视添加到整个树,但测试您感兴趣的特定部分是否已更改。这应该非常快速和容易测试(使用“get-in”查找树的正确部分)
  • Marshall通过辅助函数库对树进行所有更改,这些函数可以拦截您感兴趣的更改类型。

答案 1 :(得分:1)

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

我认为最好的方法就是创建自己的数据结构,因为基本上你要求的是像Java一样可变的HashMap,而不是Clojure Map。

您可以在现有Java HashMap周围创建一个包装器,它覆盖'put'和'putAll'方法,以便您可以检测到正在更改的内容。如果你在HashMap中有一个HashMap,你也希望子HashMap属于你的新类型,这样你就可以检测到任何级别的变化。

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

(def m (ref (WatchfulHashMap.)))

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

答案 2 :(得分:1)

我也会观看整个树并用get-in检查子集。您可以使用相同的方法快速测试子树是否已更改?测试以前的状态。像

这样的东西
(defn change-tester [tree path]
  (let [orig (get-in tree path)]
    (fn [tree]
      (not (identical? (get-in tree path) orig)))))

我不经常使用观察者所以我不知道语法,但你可以以某种方式附加上述功能,我敢肯定。