我正在使用Swing + Clojure中的GUI应用程序,该应用程序需要各种可变数据(例如滚动位置,用户数据,文件名,所选工具选项等)。
我至少可以看到处理这组数据的三种不同方式:
为所有数据的地图创建一个参考:
(def data (ref {
:filename "filename.xml"
:scroll [0 0] }))
创建各个数据元素的引用映射:
(def datamap {
:filename (ref "filename.xml")
:scroll (ref [0 0]) }))
为命名空间中的每个创建一个单独的引用:
(def scroll (ref [0 0]))
(def filename (ref "filename.xml"))
注意:将同时访问此数据,例如:通过后台处理线程或Swing事件处理线程。但是,可能不需要对多个元素进行一致的事务更新。
您的推荐方法是什么?为什么?
答案 0 :(得分:6)
首先,如果你最终只使用一个可变状态或几个独立的部分(独立,如“无论是否与另一个一致都没有意义”),为什么不使用Atoms而不是Refs?这是一个非常显着的开销减少,如果你做了很多更新,这实际上很重要。
其次,只要您仔细设计交易(即需要提及所有相关参考,有些可能需要ensure
),在单独的参考(但不是原子)中存储文件名,滚动位置等都可以。 d等 - 如果出现不一致的状态,基本上必须确保交易失败。如果您正在管理GUI状态,那么仔细设计这样的事务可能会浪费精力,其中大多数情况几乎没有变化(除了滚动位置和缓冲区内容,实际上可能经常发生变化的情况? - 我的意思是需要认真考虑的事情,因为答案应该决定最终的设计)。有许多场景,多个引用类型对象比一个更好,我只是不确定管理基本GUI状态是其中之一。 : - )
请注意,在Clojure中对引用类型对象中保存的嵌套结构执行更新非常简洁,例如: (使用Atom):
;; assuming that state-o-matic is an Atom which holds a map,
;; which holds the key of :foo, with which a vector is associated,
;; whose first item is another vector, whose first item is a map
;; which holds the key of :bar associated to a number,
;; the following increments said number
(swap! state-o-matic update-in [:foo 0 1 :bar] inc)
另见get-in
& assoc-in
。
答案 1 :(得分:1)
如果没有并发性 - 那就没有区别,你知道。
但如果它可以在不同的线程中使用,那么第一种情况会更好。因为它保证了你一贯的状态。