请分享您的想法,参与2024 年 Clojure 调查!

欢迎!请参见关于页面以了解更多关于该功能的详细信息。

0投票
Clojure
问题:clojure.data/diff 在比较不同的映射时不一致地返回一个懒惰序列,但在其他情况下返回一个向量。

user> (data/diff {:a 1 :b 2} {:a 1})
({:b 2} nil {:a 1})

这与文档和正常行为不一致。
user> (data/diff {:a 1 :b 2} {:a 1 :b 2})
[nil nil {:a 1, :b 2}]
user> (data/diff #{1 2 3} #{1 2 3})
[nil nil #{1 3 2}]
user> (data/diff #{1 2 3} #{1 2})
[#{3} nil #{1 2}]

文档字符串表示:“递归比较 a 和 b,返回 [仅在 a 中的元素 仅在 b 中的元素 两者共有的元素] 的元组”,这意味着它应该始终返回一个向量。

9 答案

0投票

评论者:yenda

修复它只需要将 diff-associative 输出向量化,如下所示

`
(defn- diff-associative
"比较关联的对象 a 和 b,比较 ks 中的关键字。"
[a b ks]
(vec (reduce
(fn [diff1 diff2]

 (doall (map merge diff1 diff2)))

[nil nil nil]
(map

(partial diff-associative-key a b)
ks))))

`

0投票

评论者:alexmiller

还有其他可能解决问题的方法,例如使用 transducers。不确定这是否值得做,但在我们进行更改时考虑它是合理的。

0投票

评论者:yenda

或许这可以作为一个改进点,在其他工单中提出。

Vec已经在diff-sequential中用于向量化列表。我建议只需修复这个bug,并添加应通过它筛选的测试案例。

0投票
评论者:yenda_

应该有一个测试案例已经失败。


[{:a #{2}} {:a #{4}} {:a #{3}}] {:a #{2 3}} {:a #{3 4}}


我得到


({:a #{2}} {:a #{4}} {:a #{3}})
0投票

评论者:alexmiller

测试可能需要更加严格,不仅要检查顺序相等性,还要检查返回的向量。

顺便问一下,这个问题是否在您的代码中引起问题,还是您只是注意到它并觉得这很奇怪?

0投票

评论者:yenda

这是一个简单的补丁,它只对映射项做了与列表相同的事情:使用vec函数创建一个新的向量。

0投票

评论者:yenda

@Alex Miller:我注意到我的程序行为中有一个bug,并追踪到(获取差异2)而不是(第2个差异),但我意识到它只在某些情况下有bug,所以我进一步调查并发现这来自于diff。

0投票

评论者:yenda

更严格的测试,检查返回的向量。

0投票
...