Clojurescript:如何有条件地更新哈希映射?

时间:2016-12-05 00:32:27

标签: clojure clojurescript reagent

我试图绕过一些CLJS和Reagent,当我尝试将一个或另一个更新应用于原子时,我遇到了一个问题。

我有一个增量函数incDieCount,它增加了地图中特定键的值。我试图写一个函数,它也应该减少一个键的值。如果值为0(它不会降低到该值以下),则它可以工作,但不是将当前值递减1,而是始终将值设置为零。我错过了什么?

(defonce app-state
  (reagent/atom
   {:dice
    {:d4 0
     :d6 0
     :d8 0
     :d10 0
     :d12 0
     :d20 0
     :d100 0}}))

(defn incDieCount [die]
  #(swap! app-state update-in [:dice die] inc))

(defn decDieCount [die]
  (let [count (get-in app-state [:dice die])]
    (if (> 0 count)
      #(swap! app-state update-in [:dice die] dec)
      #(swap! app-state assoc-in [:dice die] 0))))


(defn diceEl [[die count]]
  ^{:key die} [:li
               (str (name die) ": " count)
               [:button {:on-click (incDieCount die)}
                "Add"]
               [:button {:on-click (decDieCount die)}
                "Subtract"]])

(defn page [ratom]
  [:ul
    (for [tuple (:dice @ratom)] (diceEl tuple))])


(defn reload []
  (reagent/render [page app-state]
                  (.getElementById js/document "app")))

(defn ^:export main []
  (dev-setup)
  (reload))

2 个答案:

答案 0 :(得分:8)

要添加到@ Ming的答案:首先,您需要(> count 0)而不是(> 0 count) - 后者转换为count < 0

其次,不建议非原子地使用原子 - 在decDieCount代码中,在渲染组件时检查条件count > 0,而不是在单击按钮时(如果骰子的价值在两者之间变化?)

最好按以下方式重写decDieCount

(defn decDieCount [die]
  (fn []
    (swap! app-state update-in [:dice die]
           #(if (pos? %) (dec %) 0))))

这样可以保证骰子的新值基于其当前值。

答案 1 :(得分:1)

要获取原子的当前值,您需要取消引用它:@app-state

(let [count (get-in @app-state [:dice die])] ...)