【问题标题】:How to update fields of a Clojure record如何更新 Clojure 记录的字段
【发布时间】:2021-11-08 04:14:11
【问题描述】:

我有这个记录:

(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 记录的几个字段?

请注意,我正在寻找一个不可变的解决方案。 Clojure: Update value of record field 是关于突变的,因此不回答我的问题。

【问题讨论】:

  • 我认为assoc 可以用于记录和地图。
  • @ShannonSeverance 谢谢。也许您可以将其写为答案。 (def new-location (assoc location :z 99)) 解决问题。
  • 我不会尝试用手机写答案,也不会很快使用电脑。但艾伦提供了一个很好的答案。

标签: clojure


【解决方案1】:

您只需要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 记录。惊喜,惊喜!

my favorite template project 构建。

【讨论】:

  • “其他操作创建地图结果” - 无论如何,一些操作。任何从头开始构建新地图的东西(例如into {})当然会创建一个普通的地图。但是任何像 conjupdate 这样改变现有结构的东西都会保留记录。
  • 我澄清了文字。 m3 是我预期的地图,但令我惊讶的是 m4 仍然是一个记录。
  • 'dissoc' 仅在删除基础字段时降级为地图。例如,(dissoc m4 :extra) 产生一个点。
  • 什么是spyx?它似乎来自第三方库。
  • 是的,来自tupelo.core(use ...) 形式的“显式间谍”。也包含在模板项目的 ref 中。更多信息在这里:github.com/cloojure/tupelo#expression-debugging 它通过在输出中回显源表单和箭头=> 使打印输出更好。
猜你喜欢
  • 2013-03-20
  • 1970-01-01
  • 2021-01-16
  • 1970-01-01
  • 1970-01-01
  • 2018-05-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多