我是clojure世界的新手,我有一个疑问。 我有一个嵌套的地图,如
(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 :(得分:2)
如果要更新它们,则需要将accounts
更改为可变。通常的方法是将帐户设为atom
。那么你的功能可能如下所示:
(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
内。如果您打算将def
放在defn
内,请改用let
。在defn
之外,可以使def
更新另一个名称不同的def
,(def m2 (update-in m1 ...))
。