Welcome! Please see the About page for a little more info on how this works.

0 votes
in Clojure by
*Problem:* clojure.data/diff inconsistently returns a lazy seq when comparing different maps, but a vector otherwise.

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

This is inconsistent with doc and normal behavior :
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}]

The docstring states: "Recursively compares a and b, returning a tuple of [things-only-in-a things-only-in-b things-in-both]", implying that it should always return a vector.

9 Answers

0 votes
by

Comment made by: yenda

Fixing it just requires to vectorize diff-associative output like this :

`
(defn- diff-associative
"Diff associative things a and b, comparing only keys in 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 votes
by

Comment made by: alexmiller

There are other potential ways to address this, such as by using transducers instead. Not sure if that's worth doing, but seems reasonable to consider while we're making changes.

0 votes
by

Comment made by: yenda

Maybe this could be done as an improvement and proposed in an other ticket.

Vec is already used to vectorize the lists in diff-sequential. I would suggest to just fix the bug and add the test cases that should have screen it.

0 votes
by
_Comment made by: yenda_

There is a test case that should already fail :


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


I get


({:a #{2}} {:a #{4}} {:a #{3}})
0 votes
by

Comment made by: alexmiller

The test may need to be made more strict, checking not just for sequential equality but also for a returned vector.

Just curious - was this issue causing a problem in your code or did you just notice it and find it surprising?

0 votes
by

Comment made by: yenda

Simple patch that just does for maps what is done for lists : Creates a new vector with the vec function.

0 votes
by

Comment made by: yenda

@Alex Miller : I noticed a bug in my program behavior and traced it down to a (get diff 2) instead of (nth diff 2), but I realized that it was only buggy in some cases so I looked further and found out if was coming from diff.

0 votes
by

Comment made by: yenda

More strict tests checking for a returned vector.

0 votes
by
Reference: https://clojure.atlassian.net/browse/CLJ-1885 (reported by yenda)
...