[编辑:这个网站上如何正确格式化代码?我尝试了,但无法解决,所以我就留下了它作为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` 只接受2个参数。相反,你需要做点像这样的事情
```
(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` 函数的 `update-vals` 函数
```
(defn update-vals [m f & args]
`(clojure.core/update-vals m #(apply f % args)))
```
定义好之后,本评论中所有的示例都按预期工作。由于这是一个“增量更改”(它是现有功能的严格超集),它完全向后兼容,并且可以(也应该)包含在核心库中。
(顺便说一句,"data2" 示例是虚构的,但另一个示例与我为我的项目刚刚编写的实际代码在结构上完全相同,我将使用可变参数的 `update-vals` 包装器。)