[编辑:你如何在网站上正确地格式化代码?我尝试了却没搞定,所以就直接以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` 包装器。)