请在 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”获取的值)则携带第二个 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}]


(found playing with zach tellman's collection-check)

5答案

0 投票

评论者:michaelblume

附上展示问题的补丁(不是解决方案)

0 投票

评论者:michaelblume

进一步调查

"keys"和"vals"之间的差异源于 clojure 集合实际上使用映射作为底层实现。

持久化和瞬时的区别似乎是因为 PersistentHashSet.con 在 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

附上另一种修复方案--不是在每次瞬时的 conj 中执行包含检查,而是用 entryAt 替换 set.get。方法更侵入性,但可能更快。

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