如何更新 Clojure 记录的字段
How to update fields of a Clojure record
我有这个记录:
(defrecord Point [x y z])
(def location (Point. 1 2 3))
现在我想基于 location
创建一个新变量 new-location
,但 z
坐标已更改。我知道我可以手动复制所有字段,即 (def new-location (Point. (:x location) (:y location) 99))
,但是是否有一种更简单的方法来在功能上仅更新 Clojure 记录的几个字段?
请注意,我正在寻找一个不可变的解决方案。 是关于变异的,因此没有回答我的问题。
你只需要 assoc
:
(ns tst.demo.core
(:use demo.core tupelo.core tupelo.test))
(defrecord Point [x y z])
(dotest
(newline)
(def p1 (->Point 1 2 3))
(spyx p1)
(spyx (type p1))
(newline)
(def p2 (assoc p1 :z 99))
(spyx p2)
(spyx (type p2))
(newline)
(def m2 (into {} p1 ))
(spyx m2)
(spyx (type m2))
(newline)
(def m3 (dissoc p1 :z ))
(spyx m3)
(spyx (type m3))
(newline)
(def m4 (assoc p1 :extra 42 ))
(spyx m4)
(spyx (type m4))
)
结果
-----------------------------------
Clojure 1.10.3 Java 15.0.2
-----------------------------------
Testing tst.demo.core
p1 => #tst.demo.core.Point{:x 1, :y 2, :z 3}
(type p1) => tst.demo.core.Point
p2 => #tst.demo.core.Point{:x 1, :y 2, :z 99}
(type p2) => tst.demo.core.Point
m2 => {:x 1, :y 2, :z 3}
(type m2) => clojure.lang.PersistentArrayMap
m3 => {:x 1, :y 2}
(type m3) => clojure.lang.PersistentArrayMap
m4 => #tst.demo.core.Point{:x 1, :y 2, :z 3, :extra 42}
(type m4) => tst.demo.core.Point
请注意,简单的 assoc
将结果保留为同一类型的记录。一些操作会创建地图结果,正如我们看到的 dissoc
创建 m3
.
但是,使用 assoc
添加 :extra
字段以创建 m4
会将类型保留为 Point
记录。惊喜,惊喜!
构建
我有这个记录:
(defrecord Point [x y z])
(def location (Point. 1 2 3))
现在我想基于 location
创建一个新变量 new-location
,但 z
坐标已更改。我知道我可以手动复制所有字段,即 (def new-location (Point. (:x location) (:y location) 99))
,但是是否有一种更简单的方法来在功能上仅更新 Clojure 记录的几个字段?
请注意,我正在寻找一个不可变的解决方案。
你只需要 assoc
:
(ns tst.demo.core
(:use demo.core tupelo.core tupelo.test))
(defrecord Point [x y z])
(dotest
(newline)
(def p1 (->Point 1 2 3))
(spyx p1)
(spyx (type p1))
(newline)
(def p2 (assoc p1 :z 99))
(spyx p2)
(spyx (type p2))
(newline)
(def m2 (into {} p1 ))
(spyx m2)
(spyx (type m2))
(newline)
(def m3 (dissoc p1 :z ))
(spyx m3)
(spyx (type m3))
(newline)
(def m4 (assoc p1 :extra 42 ))
(spyx m4)
(spyx (type m4))
)
结果
-----------------------------------
Clojure 1.10.3 Java 15.0.2
-----------------------------------
Testing tst.demo.core
p1 => #tst.demo.core.Point{:x 1, :y 2, :z 3}
(type p1) => tst.demo.core.Point
p2 => #tst.demo.core.Point{:x 1, :y 2, :z 99}
(type p2) => tst.demo.core.Point
m2 => {:x 1, :y 2, :z 3}
(type m2) => clojure.lang.PersistentArrayMap
m3 => {:x 1, :y 2}
(type m3) => clojure.lang.PersistentArrayMap
m4 => #tst.demo.core.Point{:x 1, :y 2, :z 3, :extra 42}
(type m4) => tst.demo.core.Point
请注意,简单的 assoc
将结果保留为同一类型的记录。一些操作会创建地图结果,正如我们看到的 dissoc
创建 m3
.
但是,使用 assoc
添加 :extra
字段以创建 m4
会将类型保留为 Point
记录。惊喜,惊喜!