5

Why the following in emacs-lisp works as expected:

(set-difference '(1 2) '(1))
=> (2)

But if strings used it doesn't:

(set-difference '("foo" "bar") '("foo"))
=> ("foo" "bar")

How do can I calculate set difference for sets of strings?

Drew
  • 75,699
  • 9
  • 109
  • 225
iLemming
  • 1,223
  • 9
  • 14

1 Answers1

6

It is for the same reason that:

(eql "foo" "foo")
=> nil

Along with the other cl-lib sequence functions generally, set-difference (aka cl-set-difference) defaults to using eql for its equality test, and therefore in your example none of the members of the first set are present in the second set.

You can tell it what to use for its equality test, however:

(set-difference '("foo" "bar") '("foo") :test #'equal)
=> ("bar")
phils
  • 48,657
  • 3
  • 76
  • 115
  • Oh wow. I wasn't sure how to use the third arguments. Thank you very much! Sad that docstings in Emacs lisp almost never contain any examples. – iLemming Oct 07 '19 at 03:57
  • 1
    @iLemming `seq-difference` is an alternative to `cl-set-difference` and its argument is simpler: `(seq-difference SEQUENCE1 SEQUENCE2 &optional TESTFN)`. Many `cl-*` functions use `eql` by default, while I usually need `eq` or `equal`. – xuchunyang Oct 07 '19 at 04:03
  • 2
    The documentation for the various `cl-lib` facilities can seem a bit spartan, I agree, but this can be due to particular common concepts being explained in their own section elsewhere. I recommend reading `C-h i g (cl)Sequence Basics` – phils Oct 07 '19 at 04:04