Daniel Neal
Daniel Neal

Reputation: 4173

Idiomatic way to do swap! or update-in using Datomic

If I'm using a Clojure atom to keep count of something (votes for example), I can do this:

(def votes (atom {}))

(defn vote! [candidate]
  (swap! votes update-in [candidate] (fnil inc 0)))

(vote! "Abraham Lincoln")
(vote! "Abraham Lincoln")
(vote! "Winston Churchill")

votes ;=> {"Abraham Lincoln" 2, "Winston Churchill" 2}

Here, update-in neatly transforms the value at the given key, without having to look it up first.

How can I accomplish the same in Datomic? I could do something like this...

(defn vote! [db candidate]
   (let [[e v] (first (q '[:find ?e ?v 
                           :in $ ?candidate 
                           :where [[?e :name ?candidate]
                                   [?e :votes ?v]] db candidate)
     (transact! conn [{:db/id e :votes (inc v)}]))

But it seems a bit cumbersome, having to run the query, return the value and then transact with the new value. Is there a more idiomatic way of doing this (like a swap! or update-in)?

Upvotes: 1

Views: 141

Answers (1)

Randy Hudson
Randy Hudson

Reputation: 494

To me it seems most idiomatic to record the fact of the vote, then make a count query when you want to know the total. Depending on the needs of your application, this approach supports things like checking for double votes, vote change/retraction, counts in the last 24 hours, ...

Upvotes: 3

Related Questions