1

I'm new to the world of clojure and I have a doubt. I have a nested map such as

(def accounts (hash-map :XYZ (hash-map :balance (hash-map 171000 0 :171018 500 :171025 200)
                                   :statement (hash-map :171018 [{:desc "purchase" :amount 200}
                                                                 {:desc "deposit" :amount 700}]
                                                        :171025 [{:desc "purchase" :amount 300}]))

And I want to update the statements, so I wrote a simple function:

(defn add-statement
[account date desc amount]
(def accounts (update-in accounts [account :statement date] conj {:desc desc :amount amount}))

But I have a feeling that I'm doing that the wrong way...

Darakt
  • 15
  • 6

1 Answers1

2

You would need to change accounts to be mutable if you want to update them. The usual way to do this is by making accounts an atom. Then your function might look like this:

(defn add-statement! [account date desc amount]
  (swap! accounts update-in [account :statement date]
         (fn [line-items] 
           (conj (or line-items []) {:desc desc :amount amount}))))

This will add a statement line-item at a new or an existing date. The update-in is the same as yours, except that a line-item for a new date will be put into a vector rather than a list. (conj keeps the type, but it has to know the type: (conj nil :a) gives (:a)).

To turn accounts into an atom:

(def accounts (atom (hash-map ...)))

I notice your balances are not correct anyway. But if you are updating them be sure to do so in the same swap! function.

To answer your question, "Is (def m (update-in m ...)) a good practice?". Definitely not inside a defn. If you are thinking to put a def inside a defn use a let instead. Outside of a defn it would be fine to have a def that updates another def that has a different name, so (def m2 (update-in m1 ...)).

Chris Murphy
  • 6,411
  • 1
  • 24
  • 42
  • Nice, thanks for the answer. That's my first try, I was thinking about using ref (to make transaction and update several accounts at the same time) in a second try – Darakt Oct 29 '17 at 14:19