如何更改 Clojure 中的原子图?

clo*_*ark 3 clojure

我是 clojure 新手,我需要更新此原子内的两个值:

(def app-state (atom {:id "1":status 0 :st 0}))
Run Code Online (Sandbox Code Playgroud)

我使用以下内容:

(let [value (mod (+ (:st @app-state) 1) 4)]
    (swap! app-state update-in [:status] value)
    (swap! app-state update-in [:st] inc))
Run Code Online (Sandbox Code Playgroud)

我越来越:

Caused by: java.lang.ClassCastException: java.lang.Long cannot be cast to clojure.lang.IFn
Run Code Online (Sandbox Code Playgroud)

Lee*_*Lee 5

第三个参数update-in接受一个函数,但您提供了一个 long ( value),这就是您收到异常的原因。您可以assoc-in改为使用直接在映射中关联的值:

(swap! app-state assoc-in [:status] value)
Run Code Online (Sandbox Code Playgroud)

swap!但是,您应该在传递给例如的函数内以原子方式对状态进行整个更新

(swap! app-state (fn [{:keys [st] :as state}]
                    (let [st-next (inc st)
                          value (mod st-next 4)]
                       (merge state {:st st-next
                                     :status value}))))
Run Code Online (Sandbox Code Playgroud)

  • @JoelM - 你可以使用 `(swap!atom assoc key val)` 来实现。`swap!` 将现有状态作为第一个参数传递给更新函数(本例中为 `assoc`),后跟您提供的任何其他参数(此处为 `key` 和 `val`)。 (3认同)