[编辑:如何在网站上正确格式化代码?我试了,但无法解决这个问题,所以我就以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` 包装器。)