I’m sure we are thankful for the atoms that make up our body but of course I am referring to the atoms in Clojure.
Atoms are a data type that can help you “ manage shared, synchronous, independent state”. This can be wonderful when you want to access a piece of information without passing it through many functions. You can just create it and reference it.
Let me provide you with an example.
(def input-id (atom nil))
This is in my GUI file and I want to reference this input-id
in certain situations. But I want to create this reference in my argos. How can I do this?
(defn -main [& args]
(let [[game-id DB] args
game-id (when game-id (read-string game-id))
db-type (main/select-db (last args))
_load-db (data/load-db db-type)
_input-id (when (and game-id (integer? game-id))
(reset! gui/input-id game-id)))
Now you can see when I pass in an args
to -main
it can be a database or a game ID. This allows me to ask 2 questions, do I have a game id, and if I do is it an integer? If both of these are yes, then I can set that input-id
to the value that was placed into args
.
It is great having the ability to update the atom from anywhere. Now I can call it in my necessary functions.
(defn continue? []
(let [input-id (some-> @input-id int)
requested-game-map (when input-id (data/get-game-by-id input-id))])
I provided the necessary parts of this function, which is input-id
in the let statement that checks to see if the @input-id
atom is nil or not. This helps prevent me from having the nil pointer except that I kept seeing when I would not pass in a game-id
in my args
.
This allows me to potentially get the requested game if the game-id is correct.
Another time this has been helpful is when I have used this for the database and saving.
(def db-atom (atom nil))
(def log (atom {}))
(defn load-db [db-type]
(reset! db-atom db-type)
(reset! log (fetch-the-games db-type)))
I have this save multimethod that is dependent on the type of database. I have been passing along the database where it has no business being. This has been a headache and bad practice.
But now, I have my db-atom
and it can keep which database I am using and I don’t need to pass in the db
as an argument anymore. I can just create a new function called save!
and only use that when I need to.
(defn save! [game] (save game @db-atom))
The log
is another atom that has been helpful to limit the number of parameters my functions need. Now I can use the log
of the specific database I am using by only calling it once.
(defn get-game-by-id [game-id] (get @log game-id))
(defn last-game-id [] (max-game-id-edn @log))
(defn get-next-game-id [] (inc (last-game-id)))
(defn get-last-game [] (get @log (last-game-id)))
These are the ways atoms have been good to me. Until next time.
Best,
Merl