如何在Clojure中使用"Update-in"?

Zub*_*air 16 clojure

我正在尝试使用Clojure的update-in函数,但我似乎无法理解为什么我需要传递一个函数?

sep*_*p2k 30

update-in采用一个函数,因此您可以更简洁地更新给定位置的值,具体取决于旧值.例如,而不是:

(assoc-in m [list of keys] (inc (get-in m [list of keys])))
Run Code Online (Sandbox Code Playgroud)

你可以写:

(update-in m [list of keys] inc)
Run Code Online (Sandbox Code Playgroud)

当然,如果新值不依赖于旧值,assoc-in则足够且您不需要使用update-in.


seh*_*seh 5

这不是你问题的直接答案,但是为什么类似函数update-in可能存在的一个原因是效率 - 而不仅仅是方便 - 如果它能够"就地"更新地图中的值.那就是,而不是

  • 寻找地图中的钥匙,
  • 找到相应的键值元组,
  • 提取值,
  • 根据当前值计算新值,
  • 寻找地图中的钥匙,
  • 找到相应的键值元组,
  • 并覆盖元组中的值或用新元组替换元组

可以想象一个算法会省略对密钥的第二次搜索:

  • 寻找地图中的关键,
  • 找到相应的键值元组,
  • 提取价值,
  • 根据当前值计算新值,
  • 并覆盖元组中的值

不幸的是,目前的实施update-in并没有做到这种"就地"更新.它get用于提取和assoc更换.除非assoc使用最后一个查找键和相应的键值元组的一些缓存,否则assoc必须再次寻找密钥.

  • 你发现它就好像你的就地变体和实际实现之间的唯一区别是就地变体只查找键一次(这意味着`update-in`可以在以后版本的clojure中更改为使用您的就地变体而不破坏任何现有代码).然而,一个更重要的区别是,就地变体必然会改变地图,而`update-in`则不会(并且,鉴于变异方法通常在其名称中有一个`!`,不应该). (4认同)
  • 好吧,即使是非破坏性的版本也可以利用了解"击中"的位置; 甚至`assoc`需要确定原始地图的哪一部分*不会*复制而是提供更新的值. (3认同)