2017-10-28 162 views
1

我是新来到clojure的世界,我有疑问。 我有一个嵌套的地图,如Is(def m(update-in m ks f&args))a good practice?

(def accounts (hash-map :XYZ (hash-map :balance (hash-map 171000 0 :171018 500 :171025 200) 
            :statement (hash-map :171018 [{:desc "purchase" :amount 200} 
                   {:desc "deposit" :amount 700}] 
                 :171025 [{:desc "purchase" :amount 300}])) 

而且我想更新的声明,所以我写了一个简单的函数:

(defn add-statement 
[account date desc amount] 
(def accounts (update-in accounts [account :statement date] conj {:desc desc :amount amount})) 

,但我有我做了错误的感觉方式...

+0

您可以使用{}替代散列图,如:{:XYZ {:balance ....}} –

回答

2

如果您想更新它们,您需要将accounts更改为可变。通常的做法是通过账户​​。那么你的功能可能是这样的:

(defn add-statement! [account date desc amount] 
    (swap! accounts update-in [account :statement date] 
     (fn [line-items] 
      (conj (or line-items []) {:desc desc :amount amount})))) 

这将在新的或现有的日期添加一个声明行项目。 update-in与您的相同,只是将新日期的行项目放入向量而不是列表中。 (conj保持该类型,但它必须知道类型:(conj nil :a)给出(:a))。

要打开账目原子:

(def accounts (atom (hash-map ...))) 

我注意到您的余额不会反正纠正。但是如果你正在更新它们,一定要在同一个swap!函数中这样做。

要回答你的问题,“(def m (update-in m ...))是一个很好的做法?”。绝对不在defn之内。如果您正在考虑在defn内部输入def,请改为使用let。在defn之外,可以使用def来更新另一个具有不同名称的def,因此(def m2 (update-in m1 ...))将会很好。

+0

很好,谢谢您的回答。这是我第一次尝试,我正在考虑在第二次尝试中使用ref(同时进行交易和更新多个帐户) – Darakt

相关问题