Если я использую атом Clojure для подсчета чего-то (например, голосов), я могу сделать это:
(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}
Здесь update-in
аккуратно преобразует значение по заданному ключу без необходимости его предварительного поиска.
Как я могу сделать то же самое в Datomic? Я мог бы сделать что-то вроде этого...
(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)}]))
Но это кажется немного громоздким, когда приходится запускать запрос, возвращать значение, а затем выполнять транзакции с новым значением. Есть ли более идиоматический способ сделать это (например, swap!
или update-in
)?