Reputation: 1373
I would like to know if this is a good practice regarding the side effects.
Initially the code was like this:
(defn grab [item]
(if (in-stock? item)
(swap! inventory update-in [item] dec)))
but I wanted to add some logging and then return the inventory and I came up to this:
(defn grab [item]
(if (in-stock? item)
(do
(swap! inventory update-in [item] dec)
(log-sell item)
@inventory)))
which is working fine. Is "do" the right thing for this use? Are there any other practices for similar cases?
Thanks, R.
Upvotes: 1
Views: 354
Reputation: 1681
There's nothing criminal here. This style of code is common for those who have come to Clojure from such modern imperative languages as Python or Ruby.
To make this code more Clojure-like, you'd better to avoid keeping state in an atom. Just write a couple of functions that accept inventory as a map and return a new map without spoiling the previous one.
(defn grap [inv item]
(update inv item dec))
You may add logging in the middle of calling grab
having both old and new states of inventory:
(def inv-old {:cola 10})
(let [inv-new (grap inv-old :cola)]
(log "it was %s" inv-old)
(log "now it's %s" inv-new))
It is almost always possible to avoid using atoms in your code.
Upvotes: 4