[英]Using assoc-in to permanently change a value in a map Clojure
對於大量問題深表歉意。
我有一張紙牌圖:
(def cards
{
:card1 {:name "Wisp" :type "Monster" :damage 1 :health 1 :cost 0 :ability 0 :active true}
:card2 {:name "Spider Tank" :type "Monster" :damage 3 :health 4 :cost 3 :ability 0 :active true}
:card3 {:name "Boulder Fist Ogre" :type "Monster" :damage 6 :health 7 :cost 6 :ability 0 :active true}
:card4 {:name "Bloodfen Raptor" :type "Monster" :damage 3 :health 2 :cost 2 :ability 0 :active true}
:card5 {:name "Chillwind Yeti" :type "Monster" :damage 4 :health 5 :cost 4 :ability 0 :active true}
:card6 {:name "Magma Rager" :type "Monster" :damage 5 :health 1 :cost 3 :ability 0 :active true}
:card7 {:name "War Golem" :type "Monster" :damage 7 :health 7 :cost 7 :ability 0 :active true}
:card8 {:name "Oasis Snapjaw" :type "Monster" :damage 2 :health 7 :cost 4 :ability 0 :active true}
:card9 {:name "River Crocolisk" :type "Monster" :damage 2 :health 3 :cost 2 :ability 0 :active true}
:card10 {:name "Murloc Raider" :type "Monster" :damage 2 :health 1 :cost 1 :ability 0 :active true}
:card11 {:name "Northshire Cleric":type "Monster" :damage 1 :health 3 :cost 1 :ability 2 :active true}
:card12 {:name "Nat Peagle" :type "Monster" :damage 0 :health 4 :cost 2 :ability 4 :active true}
:card13 {:name "Molten Giant" :type "Monster" :damage 8 :health 8 :cost 20 :ability 0 :active true}
}
)
這些卡在組成我的董事會的列表中:
(def board1 (list (:card3 cards) (:card4 cards) (:card11 cards) nil nil nil nil))
我要做的是將卡上的活動標志從true更改為false。
我知道我可以直接通過以下方式對我的卡片收集執行此操作:
user=> (assoc-in (:card11 cards) [:active] false)
{:ability 2, :name "Northshire Cleric", :type "Monster", :damage 1, :active false, :health 3, :cost 1}
我正在嘗試構建一個功能,當給定一個集合(板)和一個數字(第n個)卡時。 使此板上的此卡永久錯誤。
我一直在嘗試原子,但到目前為止還沒有喜悅。
(test-function board1 1)
(defn test-function [coll number]
(let [test (atom coll)]
(swap! test assoc-in (get (nth @test number)) [:active] false)
(println test)))
我想知道我在做什么錯,以及是否有一種更清潔的方法而不使用原子。
您需要在let
塊之外聲明原子。 您擁有它的方式,每次都會重新綁定它。 atom
是有狀態事物的不錯選擇,因此應這樣聲明您的原子:
(def cards (atom
{:card1 {:name "Wisp" :active true}
:card2 {:name "Spider Tank" :active true}}))
然后,您可以編寫函數以將false
交換為false
如下所示:
(defn myfunc [coll number]
(swap! coll assoc-in [(str :card number) :active] false ))
您不需要兩種不同的功能,盡管其中一種用於設置為true
,另一種用於設置為false
。 您應該下一步,讓它讀取當前的布爾值,然后將相反的值assoc-in
。 (還請注意,我將樣本數據樣本保持為很小)。 ;)
JT93
根據您的評論,您希望消除atom
,並采用干凈的更新方法。
如果您可以在問題中提供更多信息來永久性地闡明您的意思。 例如:您是否要在整個執行周期內保持卡的板狀態? 如果是這樣,盡管Clojure另外還有一些其他方法,您可能需要使用atom
。
首先,考慮將board1
的定義board1
為向量而不是列表。 然后,您可以消除神秘的邏輯,而只需很少吹牛就可以使用assoc-in
:
(def board1 [(:card3 cards) (:card4 cards) (:card11 cards) nil nil nil nil])
(defn test-function [coll number]
(assoc-in coll [number :active] false))
(clojure.pprint/pprint (test-function board1 0))
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.