给定以下情况:
(defrecord Person [firstname lastname])
(def some-map (ref {}))
(dosync
(alter some-map conj {1 (Person. "john" "doe")})
(alter some-map conj {2 (Person. "jane" "jameson")}))
要将"joe"的名字更改为"nick",我执行以下操作:
(dosync
(alter some-map (fn [m]
(assoc m 1
(assoc (m 1) :firstname "nick")))))
在Clojure中这样做的惯用方式是什么?
无需使用更新,对于这种情况,assoc-in正是您想要的。
(dosync (alter some-map assoc-in [1 :firstname] "nick"))
编辑:对于您的示例,assoc-in
更好,因为您忽略了以前的值。对于实际需要上一个值的情况,请保留此答案:
update-in
用于更新嵌套结构:
(alter some-map update-in [1 :firstname] (constantly "nick"))
最后一个参数是要"替换"的值上的函数(如assoc
,它不替换但返回一个新结构。在这种情况下,旧值将被忽略,因此始终返回"nick"的constantly
函数。