Ниже приведен сеанс repl, основанный на вашей проблеме.Сначала я определяю app-state
именно так, как вы отправили.Затем я определяю bump-state
как анонимную функцию #(…)
, которая принимает один аргумент, текущее значение app-state
, обозначаемое заполнителем %
.Форма let
связывает увеличенное значение клавиши :st
с st
.Наконец, assoc
возвращает новую неизменяемую карту, связывая новые значения с :st
и :status
предыдущей карты.
Следующие несколько строк просто вызывают swap!
, чтобы подтвердить, что bump-state
работает.Последняя строка просто определяет анонимную функцию непосредственно при вызове swap!
.Хотя принятый ответ работает нормально, я думаю, что это немного более кратко.
user=> (def app-state (atom {:id "1":status 0 :st 0}))
#'user/app-state
user=> (def bump-state #(let [st (inc (:st %))] (assoc % :st st :status (mod st 4))))
#'user/bump-state
user=> (swap! app-state bump-state)
{:id "1", :status 1, :st 1}
user=> (swap! app-state bump-state)
{:id "1", :status 2, :st 2}
user=> (swap! app-state bump-state)
{:id "1", :status 3, :st 3}
user=> (swap! app-state bump-state)
{:id "1", :status 0, :st 4}
user=> (swap! app-state #(let [st (inc (:st %))] (assoc % :st st :status (mod st 4))))
{:id "1", :status 1, :st 5}
Вся идея swap!
заключается в том, что ваша функция обновления работает с текущим неизменяемым значением, которое хранитсяатомом и возвращает новое неизменное значение, чтобы заменить его.Ваша функция обновления - это просто чистая функция, которая позволяет вам легче рассуждать об этом, а также играть с ней в реплее, как и другие функции.