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

Have I some way to store global data collections in Clojure?

提问人:Дмитрий Волоснихин 提问时间:8/11/2015 更新时间:8/11/2015 访问量:190

问:

我需要一种在 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)]

有人有办法让我用它来完成这样的任务吗?谢谢

收集 Clojure(克洛朱尔酒店) 全局变量 可变

评论


答:

2赞 leonardoborges 8/11/2015 #1

看看原子

您的示例可以适应如下所示(未经测试):

; 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!是以线程安全的方式更新原子值的方法。此外,请注意,上述对集合的引用前面有 @ 符号。这就是你如何获得原子中包含的值。@ 符号是 的缩写。(deref collection)

评论

0赞 Дмитрий Волоснихин 8/11/2015
哇!看起来原子以我需要的方式工作。谢谢!
0赞 nha 8/11/2015
顺便说一句,而不是与全局变量和原子一起使用很有趣。defoncedef
0赞 Дмитрий Волоснихин 8/12/2015
谢谢,我也会看看这个功能!