将包含可能为空的基元数组的嵌套数据结构与 clojure 进行比较。data/diff

Comparing nested data structures containing potentially empty arrays of primitives with clojure.data/diff

我正在使用 clojure。data/diff 在我的单元测试中比较嵌套数据结构。它工作得很好,直到我遇到它(IMO)在遇到空的基元数组时表现不一致的问题。

非空基元数组与包含相同类型对象(例如双精度对象)的向量相比效果很好。但是,空原始数组不等于(在 diff 函数的意义上)一个空向量甚至另一个相同类型的空数组。

这是一个显示我的问题的 repl 会话。我添加了一些评论。

nerom.nsd.dbserver=> (require '[clojure.data :as cd])
nil
;; this is as I would expect - a vector and a primitive array with 
;; same contents compare equal
nerom.nsd.dbserver=> (cd/diff [[1.1 2.2]] [(double-array [1.1 2.2])])
[nil nil [[1.1 2.2]]]
;; this is inconsistent with the previous - empty double array does 
;; not compare equal to an empty vector
nerom.nsd.dbserver=> (cd/diff [[]] [(double-array [])])
[[nil] [nil] nil]
;; two double arrays with the same contents compare equal
nerom.nsd.dbserver=> (cd/diff [(double-array [1.1 2.2])] [(double-array [1.1 2.2])])
[nil nil [[1.1 2.2]]]
;; except when they are empty, which is IMO inconsistent
nerom.nsd.dbserver=> (cd/diff [(double-array [])] [(double-array [])])
[[nil] [nil] nil]

如何使空数组与空向量或至少相同类型的空向量相比较?

我想我找到了线索:

如果您查看 diff 来源,您会看到以下内容:

(if (= a b)
    [nil nil a]
    (if (= (equality-partition a) (equality-partition b))
      (diff-similar a b)
      (atom-diff a b)))

首先将两个值与协议 EqualityPartition 中定义的 equality-partition 进行比较,returns 一些关键字相等性 class

因此,如果您将此协议扩展到原始数组,它们将不会被视为相等:

(require '[clojure.data :as d])

之前:

user> (d/diff [(double-array [])] [(int-array [])])
[[nil] [nil] nil]

然后扩展协议:

(extend-protocol d/EqualityPartition
  (Class/forName "[D")
  (equality-partition [_] :double-array))

(extend-protocol d/EqualityPartition
  (Class/forName "[I")
  (equality-partition [_] :int-array))

user> (d/equality-partition (double-array []))
:double-array
user> (d/equality-partition (int-array []))
:int-array

之后:

user> (d/diff [(double-array [])] [(int-array [])])
[[#object["[D" 0x1e2f0f97 "[D@1e2f0f97"]] [#object["[I" 0x207c60b5 "[I@207c60b5"]] nil]

而相似类型的数组将像以前一样进行比较

user> (d/diff [(double-array [])] [(double-array [])])
[[nil] [nil] nil]

user> (d/diff [(double-array [1])] [(double-array [10])])
[[[1.0]] [[10.0]] nil]

因此进一步朝这个方向看:您可以调整扩展此协议(以及 clojure.data 中的其他协议)的比较