2024 Clojure 状态调查!中分享您的想法。

欢迎!请查看关于页面以了解更多相关信息。

0
集合

(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”调用 invoke 获取的值)携带了第二次 conj! 的元数据。这*不*符合不使用瞬态时的行为


(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.cons 在 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

评论由:michaelblume

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

0

评论由:michaelblume

附上替代的修复方案--而不是对每个临时集合联集进行包含性检查,而是使用 entryAt 重写 back set.get。更侵入性,但可能更快。

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