我有办法在Clojure中存储全局数据集吗?

时间:2015-08-11 06:41:30

标签: collections clojure global-variables mutable

我需要在Clojure中全局存储一些数据的方法。但我找不到这样做的方法。我需要在运行时加载一些数据并将其放到全局对象池中,以便稍后进行操作。应该在一些函数集中访问这个池来设置/从中获取数据,就像某种类似于内存的数据库一样,具有类似哈希的语法来访问。

我知道在函数式编程中它可能是错误的模式,但我不知道存储动态对象集以在运行时访问/修改/替换它的其他方法。 java.util.HashMap是某种解决方案,但无法使用序列函数访问它,当我需要使用这种集合时,我会错过Clojure的灵活性。 Lisps语法很棒,但即使开发人员在某些地方不需要它,它仍然有点卡在纯度上。

这是我想要使用它的方式:

; Defined somewhere, in "engine.templates" namespace for example
(def collection (mutable-hash))

; Way to access it
(set! collection :template-1-id (slurp "/templates/template-1.tpl"))
(set! collection :template-2-id "template string")

; Use it somewhere
(defn render-template [template-id data]
  (if (nil? (get collection template-id)) "" (do-something))) 

; Work with it like with other collection
(defn find-template-by-type [type]
  (take-while #(= type (:type %)) collection)]

有人可以使用这种方式来完成这样的任务吗?谢谢

1 个答案:

答案 0 :(得分:2)

看看atoms

你的例子可以适应这样的事情(未经测试):

; Defined somewhere, in "engine.templates" namespace for example
(def collection (atom {}))

; Way to access it
(swap! collection assoc :template-1-id (slurp "/templates/template-1.tpl"))
(swap! collection assoc :template-2-id "template string")

; Use it somewhere
(defn render-template [template-id data]
  (if (nil? (get @collection template-id)) "" (do-something))) 

; Work with it like with other collection
(defn find-template-by-type [type]
  (take-while #(= type (:type %)) @collection)]

swap!是如何以线程安全的方式更新atom的值。另外请注意,上面的集合的引用已经由@符号添加。这就是你获得原子中包含的值的方法。 @符号是(deref collection)的缩写。