使用Java中的地图,您可以编写map.computeIfAbsent(key, f)
来检查地图中是否存在密钥,如果没有,则在密钥上调用f
以生成值,并在地图中输入该值。您还有map.putIfAbsent(key, value)
,如果地图中尚不存在该键,则只会将该值放入地图中。
忽略Java方法也返回值的事实,而是想要返回新映射,Clojure中的等效代码是什么?
到目前为止,我提出的最好的方法就是用
之类的东西来推销自己(defn compute-if-absent [map key f]
(if (key map)
map
(assoc map key (f key))))
有替代方法可以自己滚动吗?
答案 0 :(得分:5)
Clojure映射是不可变的,因此您将始终返回具有更新内容的新映射 - 因此您的函数将始终是线程安全的。这也意味着您不能拥有一个全局变量来保存您的地图并将其变异。
您compute-if-absent
的实施几乎是正确的。对于虚假的密钥,它将失败,例如{false 1}
。您需要更改if
条件并使用contains?
代替key
:
(defn compute-if-absent [m k f]
(if (contains? m k)
m
(assoc m key (f k))))
如果确实需要与ConcurrentMap
具有相同的行为,则可以在Clojure中使用Java互操作来使用它们。
答案 1 :(得分:2)
更简单的解决方案是merge
使用put-if-absent
:
(merge {key val} m)
虽然compute-if-absent
的最终结果是相同的,但无论(f key)
的内容如何,以下代码当然会计算m
:
(merge {key (f key)} m)
答案 2 :(得分:0)
如果您尝试实施某种形式的缓存,那么您可以使用clojure的memoize
功能。
示例:(def fast-inc (memoize inc))