2016-02-18 36 views
0

對於大量問題感到抱歉。使用assoc-in永久更改地圖中的值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)) 

我想要做的就是改變活動標誌的卡片上從真實的假。

我知道我可以直接這樣做是爲了我的卡片收集:

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))) 

我想知道我在做什麼錯,是否有更乾淨的方式來做到這一點,而不使用原子。

+3

這是什麼意思,「永久」在這裏?另外,你應該使用boolean'true'和'false'而不是'f'和't'字符串。 – jmargolisvt

+0

我會改變爲真和假。根據我的理解,當我將「真」改爲「假」時,它不會保持錯誤。如果可能的話,我希望它在函數的持續時間內保持真或假。 – JT93

+0

@ JT93「改變」是什麼意思? –

回答

2

JT93

根據你的評論,你想要做掉與​​,有一個乾淨的更新方式。

如果你可以在你的問題中澄清你的意思是永久性的更多信息。例如:你想在整個執行期間保持卡的狀態嗎?如果是這樣,您可能需要使用​​,但Clojure除此之外還有幾種不同的方法。

首先,考慮將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)) 
2

您需要在let塊之外聲明原子。你擁有它的方式,你每次都重新綁定它。該​​是有狀態的東西是不錯的選擇,讓你的聲明原子像這樣:

(def cards (atom 
    {:card1 {:name "Wisp" :active true} 
    :card2 {:name "Spider Tank" :active true}})) 

然後,你可以寫你的函數false交換像這樣:

(defn myfunc [coll number] 
    (swap! coll assoc-in [(str :card number) :active] false)) 

你不想要兩個不同的功能,其中一個設置爲true,另一個設置爲false。你應該採取這個下一步,並使其讀取當前的布爾值,然後assoc-in相反的值。 (另請注意,我保持示例數據樣本非常小)。 ;)

+0

''更新'與'不''似乎是做最後一個更好的方法。 – Magos

+0

根據原始問題,卡片在列表中,數字是列表中的索引。如您所示,創建一個字符串將直接在地圖上工作,但不在列表中。 –