【发布时间】:2022-11-30 00:38:38
【问题描述】:
在 clojure 中,要编辑映射键的值,有 2 个选项可用:
update-
assoc我可以从 clojure 文档中找到的唯一区别是
update函数执行以下额外操作:如果键不存在,则 nil 作为旧值传递。
除此以外,是否有任何我应该使用更新或关联的特定用例?
或者在哪些情况下我应该更喜欢什么(如果我错过了这些用例)。
【问题讨论】:
标签: functional-programming clojure
在 clojure 中,要编辑映射键的值,有 2 个选项可用:
updateassoc
我可以从 clojure 文档中找到的唯一区别是 update 函数执行以下额外操作:
如果键不存在,则 nil 作为旧值传递。
除此以外,是否有任何我应该使用更新或关联的特定用例?
或者在哪些情况下我应该更喜欢什么(如果我错过了这些用例)。
【问题讨论】:
标签: functional-programming clojure
如果使用得当,它们都会在您的代码中明确说明意图:
assoc 提示读者,新的添加 kv 对(或
替换现有键的值)并且它们往往不是
依赖于该键的当前值。update 提示,键的一个值得到更新,原始值
值(如果存在)可用于此计算。
(update {} :a (fnil inc 0))
; → {:a 1}
(update {:a 41} :a (fnil inc 0))
; → {:a 42}
(assoc {:z 0} :a 42 :b 23}
; → {:z 0, :a 42, :b 23}
【讨论】:
你用assoc模拟update如下
(assoc m :foo (f (:foo m)))
看起来很笨重,最好是:
(update m :foo f)
它返回一个新映射,f 应用于与 :foo 键对应的值。
【讨论】:
update的实现方式
m 的值效果不佳,这些值计算起来很昂贵或有副作用。如果您需要更新键的值并且您关心以前的值,update 是可行的方法。
update被实现为(defn update [m k f] (assoc m k (f (get m k)))),为什么是OP的版本对于计算成本高或有副作用的 m 值效果不佳? get 比使用关键字作为函数更好吗?
(assoc (expensive-map) k (f (get (expensive-map) k))) 和(update (expensive-map) k f) 之间的区别。因为 update 是一个函数,所以它的参数自然只会被求值一次。但是如果你使用assoc,你必须走得更远以避免重复评估地图。