[编辑:在这个网站上如何正确格式化代码?我试了,但没有弄明白,所以我就以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`函数
```
(defn update-vals [m f & args]
(clojure.core/update-vals m #(apply f % args))
```
定义了之后,本注释中的所有示例都按预期工作。由于其为一个“累积式更改”(它是现有功能的严格子集),因此它是完全向下兼容的,并且可以(也应该)包含在核心库中。
另外,为了记录,`data2`示例是人为设置的,但另一个示例与我为我的项目刚刚编写的实际代码结构相同,并且我将使用可变参数`update-vals`包装器。