与两个元素的关联和update / assoc之间的差异

时间:2017-02-18 22:31:05

标签: clojure functional-programming hashmap

我一直在做(assoc-in my-hash [:data :id] 1)这样的事情,看起来很不错。

最近,由于我很少有两个以上的关卡,我注意到我可以做(update my-hash :data assoc :id 1),听起来完全不同,但返回相同。

所以,我想知道,性能有什么不同吗?你认为它在某种程度上比另一种更具可读性吗?更惯用吗?

update / assoc对我来说感觉更贵,但我真的比assoc-in更喜欢它,这让我每次看到它都会停下来思考。

1 个答案:

答案 0 :(得分:5)

在性能方面,衡量总是好的。理想情况下,您要组装一个真实的地图(无论您的地图是大还是小都会对各种操作的相对成本产生一些影响),并使用Criterium两种方式进行尝试:

(require '[criterium.core :as c])

(let [m (construct-your-map)]
  (c/bench (assoc-in m [:data :id] 1))
  (c/bench (update m :data assoc :id 1)))

在幕后,update + assocassoc-in的展开版本,这里不需要辅助向量来保存密钥,所以我希望它比assoc-in快。但是(1)通常我不担心这样的事情会有轻微的性能差异,(2)当我关心时,再次测量比测量更好。

(在我的方框中,使用Clojure 1.9.0-alpha14,update + assoc确实在~282 ns时更快,assoc-in为{35} ns测试(assoc (into {} (map #(vector % %)) (range 20)) :data {:id 0})的地图。)

最终,大部分时间的可读性将是更重要的因素,但我认为你不能说一般方法比另一种方法更具可读性。如果您的链已经多次使用assoc-inupdate,为了保持一致性,可能最好重复相同的功能(只是为了避免让读者感到惊讶“是这件事真的不同“)。如果您拥有一个可以控制的代码库,那么您可以采用一种“家居风格”,这种风格有利于一种方法而不是另一种方式。等等。

我可能会在大多数情况下看到assoc-in更具可读性 - 它使用单个“动词”并且一目了然地说明更新的(单个,精确)路径是什么 - 但是如果您更喜欢update + assoc并期望在代码库中保持一致使用,这当然也很好。