multiset
multiset copied to clipboard
Set equality
I think it would make sense for a multiset to equal a set when the elements are the same. This PR implements that (in both directions): (= set multiset) is enabled by making multiset implement the java.util.Set interface, and (= multiset set) is handled in the .equals method.
I also changed the .hashCode algorithm to match that used by java.util.Set, and added support for Clojure's hash algorithm, so that when a set and a multiset are equal, their (Java and Clojure) hashes will also be equal.
Does this look reasonable to you?
Ping @achim: any feedback on this?
I think it makes sense (as, for example, (= [1 2 3] '(1 2 3)) is also true, even if they have different types).
It also makes it easier to use multisets in tests, as you can just compare to a set literal when you don't expect any duplicates, e.g.:
(defn foo
[c]
(into (multiset)
(map #(* % 2) c)))
(deftest foo-test
(is (= (foo [1 2 3])
#{2 4 6})))
@emlyn Thanks for the PR! I'm sorry for the delay, I'll hopefully have a chance to look at this on the weekend.
I just realised there is a slight issue in the equality comparison to a java.util.Set in that it assumes the elements of the other set are distinct. That might not be the case if it is another multiset (although it would have to be a different implementation as this one is already handled).
So I've changed the equality check so that it works even if the other set has duplicate elements. I've then added special cases for Clojure sets and AbstractSets so that in the most common cases it can use the faster check (although I haven't benchmarked it, so maybe those two cases aren't really needed?).