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!开始的元数据,而"值"(通过调用invoke与"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"和"values"之间的差异源于Clojure集合在底层使用映射的事实。

持久性和临时的区别似乎是因为 PersistentHashSet.cons 在 contains (详见这里的代码) 上进行短路,而 ATransientSet.conj 则没有进行短路(详见这里的代码

在 ATransientSet.conj 中添加包含检查可以使行为保持一致并且通过附件测试,但我预计这可能会对性能产生影响。有什么想法吗?

0

评论者:michaelblume

附上建议的修复方案--请注意,这可能会导致临时集合的性能下降。

0

评论者:michaelblume

附加一个替代修复方案--而不是在每次临时 conj 上执行包含检查,而是用 entryAt 替换 set.get。更激进,但可能更快。

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