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

I need the way to store some data globally in Clojure. But I can't find the way to do that. I need to load some data in runtime and put it to a global pool of objects, to manipulate with it later. This pool should be accessed inside some set of functions to set/get data from it like a some sort of small in-memory database with hash-like syntax to access.

I know that it might be bad pattern in functional programming, but I don't know other way to store dynamic set of objects to access/modify/replace it in runtime. java.util.HashMap is some sort of solution, but it couldn't be accessed with sequence functions and I miss flexibility of Clojure when I need to use this kind of collection. Lisps syntax are a great, but it's a bit stucks on purity even if developer doesn't need it in some places.

This is the way I want to work with it:

; 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)]

Have someone a way I can use for tasks like this? Thank you

Upvotes: 1

Views: 207

Answers (1)

leonardoborges
leonardoborges

Reputation: 5629

Have a look at atoms.

Your example could be adapted to something like this (untested):

; 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! is how you can updated the value of an atom in a thread-safe manner. Additionally note that references to collection above have been prepended by the @ sign. That is how you get the value contained in an atom. The @ sign is short for (deref collection).

Upvotes: 2

Related Questions