我一直在做(assoc-in my-hash [:data :id] 1)
这样的事情,看起来很不错。
最近,由于我很少有两个以上的关卡,我注意到我可以做(update my-hash :data assoc :id 1)
,听起来完全不同,但返回相同。
所以,我想知道,性能有什么不同吗?你认为它在某种程度上比另一种更具可读性吗?更惯用吗?
update / assoc
对我来说感觉更贵,但我真的比assoc-in
更喜欢它,这让我每次看到它都会停下来思考。
答案 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
+ assoc
是assoc-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-in
或update
,为了保持一致性,可能最好重复相同的功能(只是为了避免让读者感到惊讶“是这件事真的不同“)。如果您拥有一个可以控制的代码库,那么您可以采用一种“家居风格”,这种风格有利于一种方法而不是另一种方式。等等。
我可能会在大多数情况下看到assoc-in
更具可读性 - 它使用单个“动词”并且一目了然地说明更新的(单个,精确)路径是什么 - 但是如果您更喜欢update
+ assoc
并期望在代码库中保持一致使用,这当然也很好。