[编辑:如何在网站上正确格式化代码?我试了,但做不到,所以就直接用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` 函数,该函数包装现有的函数。
```
(定义update-vals函数[d m f & args]
使用clojure.core/update-vals m #(apply f % args))
```
定义好后,本段评注中的所有示例都按预期工作。由于这属于“累加式变更”(它是现有功能的严格超集),与其完全兼容,因此可以(应该)将其包含在核心库中。
(顺便提一句,`data2`示例是人为设定的,但另一个示例在结构上与我刚刚为我的项目编写的实际代码完全相同,我将会使用变长参数的`update-vals`包装器。)