[编辑:如何在网站上正确格式化代码?我尝试了,但无法解决这个问题,因此我只是把它当作markdown格式。]
您还考虑添加 `update-keys` 和 `update-vals` 的可变参数情况吗?我在发现我的用例不支持后感到惊讶,并且我认为我有一个相当有说服力的例子表明这是必要的。
我有一个类似这样的数据结构(以及稍后要使用的谓词)
```
(def data {:foo {0 {:bar [10 42 11 12]}
1 {:bar [20 21 42 22]}
,,, }})
(def my-special-pred (complement #{42}))
```
(注意 `(data :foo)` 中可以有不定数量的项目;三个逗号应类似省略号。)
假设我想更新 `:foo 0 :bar` 中的向量。这可以通过以下方式完成
```
(update data :foo update 0 update :bar (partial filter my-special-pred))
```
在这种情况下,您也可以只使用 `update-in`(您可能应该这样做)。但是,如果您想对 `:foo` 映射中的所有值都这样做,而不仅仅是0的情况怎么办?您应该能够只使用
```
(update data :foo update-vals update :bar (partial filter my-special-pred))
```
但不行,因为 `update-vals` 只接受两个参数。相反,您需要执行类似以下操作
```
(update data :foo update-vals #(update % :bar (partial filter my-special-pred)))
```
这比最初看起来更不方便;由于匿名函数字面量不允许嵌套,您不能使用另一个一个函数(例如)作为谓词。但是,如果您有一个可变参数的 `update-vals`,您就可以这样做
```
(update data :foo update-vals update :bar (partial filter #(not= 0 (mod % 42))))
```
出于同样的原因,您不能轻易地使用多个“`update-vals`”层级,如下所示
```
(def data2 {0 {:top 200
:bottom 201
,,, }
1 {:left 300
:right 301
,,, }})
(update-vals data2 update-vals inc)
```
有各种解决方法,但最干净、最佳的方法似乎就是自己编写一个包装现有函数的 `update-vals` 函数
```
(defn update-vals [m f & args]
(clojure.core/update-vals m #(apply f % args)))
```
定义此函数后,此评论中的所有示例都按预期工作。而且,由于这是一项“累积变更”(它是现有功能的严格子集),因此它是完全向后兼容的,并且可以(应该)包含在核心库中。
(另外,为了记录,`data2` 的示例是虚构的,但另一个示例在结构上与我为我的项目编写实际代码时使用的代码相同,我将使用可变参数的 `update-vals` 包装器。)