【问题标题】:Have I some way to store global data collections in Clojure?我有什么方法可以在 Clojure 中存储全局数据集合吗?
【发布时间】:2015-08-11 06:41:30
【问题描述】:

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

有什么方法可以让我完成这样的任务吗?谢谢

【问题讨论】:

    标签: collections clojure global-variables mutable


    【解决方案1】:

    看看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! 是您可以以线程安全的方式更新原子值的方法。另外请注意,上面对集合的引用已由 @ 符号前置。这就是您获取原子中包含的值的方式。 @ 符号是(deref collection) 的缩写。

    【讨论】:

    • 哇!看起来原子以我需要的方式工作。非常感谢!
    • 附带说明,defonce 而不是 def 与全局变量和原子一起使用很有趣。
    • 谢谢,我也看看这个功能!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-13
    • 2020-09-23
    • 2023-03-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多