Search code examples
clojuresetset-theory

clojure.set/difference fails when result would is empty and right set has higher cardinality


I try to eleminate elements from a set, that are present on a different sequence in Clojure. But the clojure.set/difference doesn't seem to work as I expect it. Where is my error?

Some examples:

Removing empty sequence

(difference #{3 2} '())

Result: #{3 2} (as expected)

Removing some of the elements

(difference #{3 2} '(3))

Result: #{2} (as expected)

Removing elements not present in the set

(difference #{3 2} '(1))

Result: #{3 2} (as expected)

Removing all elements

(difference #{3 2} '(2 3))

Result: #{} (as expected)

Removing more elements that present

(difference #{3 2} '(1 2 3))

Instead of a result I get IllegalArgumentException contains? not supported on type: clojure.lang.PersistentList clojure.lang.RT.contains (RT.java:814)

Expected result: #{}

So it seems, that the clojure.set/difference function fails, when the result is the empty set and the set of elements to be removed has a higher cardinality than the original set. But the question is: why doesn't this work? I'd expect that this is a legal application of clojure.set/difference.


Solution

  • This doesn't work because the difference function compares the sizes of the two inputs and iterates over the smaller collection and removes elements from the first one. If the second argument is larger, it uses contains? to see if an item in the first collection exists in the second. contains? is not supported on lists so you get the exception.

    The functions in clojure.set should only be called with set arguments.