Clojure 2024状态调查中分享你的看法!

欢迎!请查看关于页面了解更多关于该功能的信息。

0
Collections

(let [s (-> #{}
          transient
          (conj! (clojure.core/with-meta [-7] {:mynum 0}))
          (conj! (clojure.core/with-meta [-7] {:mynum -1}))
          persistent!)]
  [(meta (s [-7])) (meta (first s))])
=> [{:mynum -1} {:mynum 0}]


基本上,"key"(通过在集合上迭代获得的值)保留了第一个 conj! 的元数据,而"value"(通过调用 "key" 获得的值)携带第二个 conj! 的元数据。如果不用 transients,这种行为是不会出现的。


(let [s (-> #{}
          (conj (clojure.core/with-meta [-7] {:mynum 0}))
          (conj (clojure.core/with-meta [-7] {:mynum -1}))]
  [(meta (s [-7])) (meta (first s))])
=> [{:mynum 0} {:mynum 0}]


(在玩 zach tellman 的 collection-check 时被发现)

5答案

0

评论者:michaelblume

附上展示问题的补丁(不是修复程序)

0

评论者:michaelblume

更多调查

"keys"和"vals"之间的差异是由于Clojure集合在底层使用映射。

持久性和瞬态之间的差异似乎是由于 PersistentHashSet.conj 在 contains 上短路(https://github.com/clojure/clojure/blob/clojure-1.6.0/src/jvm/clojure/lang/PersistentHashSet.java#L97),而 ATransientSet.conj 不短路(https://github.com/clojure/clojure/blob/clojure-1.6.0/src/jvm/clojure/lang/ATransientSet.java#L27)。

在 ATransientSet.conj 中添加包含检查可以使行为一致并通过附加的测试,但我认为这可能会降低性能。有何看法?

0
by

评论者:michaelblume

附加了建议的修复方案--请注意,这可能会对临时集合的性能产生影响。

0
by

评论者:michaelblume

附加了另一种修复方案--不是对每个临时 conj 进行包含检查,而是使用 entryAt 替换 set.get。更具侵入性但可能更快。

0
by
参考: https://clojure.atlassian.net/browse/CLJ-1615(由 michaelblume 报告)
...