data-structures - 使用交换!更新 Clojure(Script) 原子中的 map 向量

标签 data-structures clojure clojurescript

我有一个持有 map 向量的原子(来自 c2 库的示例代码):

(def ^:export data
  (atom [{:metric "Revenue", :units "USD in thousands"
           :ranges [150 225 300], :measurements [220 270], :markers [250]}
          {:metric "Profit", :units "%"
           :ranges [20 25 30], :measurements [21 23], :markers [26]}
          {:metric "Order Size", :units "USD average"
           :ranges [350 500 600], :measurements [100 320], :markers [550]}
          {:metric "New Customers", :units "count"
           :ranges [1400 2000 2500],
           :measurements [1000 1650], :markers [2100]}
          {:metric "Satisfaction", :units "out of 5"
           :ranges [3.5 4.25 5], :measurements [3.2 4.7], :markers [4.4]}]))

我可以很容易地修改(好吧,创建一个修改后的副本),增加 :markers 的值, 因此:
(map (fn [m] (update-in m [:markers] (fn [v]  (map inc v)))) @data)

我熟悉用 swap! 更新原子在大多数情况下,但在这种情况下我能做的最好的是:
(defn upmark []
  (let [new (map (fn [m] (update-in m [:markers] (fn [v]  (map inc v)))) @data)]
    (vec (reset! data new))))

这显然很糟糕,因为我正在重置原子的整个状态,而不仅仅是更新我需要的部分。我只是很困惑,为什么使用 swap! 将执行所需操作的代码应用于普通 map 向量如此困难? .我明白了 swap!有一个隐含的 apply但我似乎无法正确应用 fn。

最佳答案

你真的很亲近。 (swap!)将给定的函数应用于原子中的当前值以及传递给交换的任何其他参数。因此,您可以定义一个作用于 map 向量的函数,然后使用 (swap!)将其应用于原子中的值:

(def ^:export data (atom ...))

(defn upmark [data]
    (mapv (fn [m] (update-in m [:markers] (fn [v]  (mapv inc v)))) data))

(swap! data upmark)

请注意,我更改了几个实例 (map)(mapv)所以向量不会变成惰性序列。

关于data-structures - 使用交换!更新 Clojure(Script) 原子中的 map 向量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25755522/

相关文章:

java - 如何存储文件结构类型的数据以便于检索和插入

java - 将 Java 类导入 Clojure

clojure - 我如何在 clojure 中创建一个大向量

javascript - 将 javascript 翻译为 Clojurescript

clojure - 如何在不发出ajax请求的情况下将edn从clojure传递到clojurescript(即通过hiccup生成的页面)

clojure - 为什么我不能 :require :refer in clojurescript?

c - 如何评估 c 中的结构并通过指针变量给出输入?

performance - AVL 树上的二叉搜索树

recursion - 用于计算组合的尾递归 Clojure 函数

algorithm - 查询数组中的两个整数是否相差D