>From 2f00c34ecec39c5c90e6c3ef2f5ab40fa60979e9 Mon Sep 17 00:00:00 2001 From: Damien Cassou Date: Mon, 17 Apr 2017 11:01:39 +0200 Subject: [PATCH] Add cl-set-equal to test for set equality * lisp/emacs-lisp/cl-seq.el (cl-set-equal): Add function to compare two lists as if they were sets. * test/lisp/emacs-lisp/cl-seq-tests.el (cl-set-equal): Add test for cl-set-equal. --- doc/misc/cl.texi | 6 ++++++ etc/NEWS | 3 +++ lisp/emacs-lisp/cl-seq.el | 10 ++++++++++ test/lisp/emacs-lisp/cl-seq-tests.el | 16 ++++++++++++++++ 4 files changed, 35 insertions(+) diff --git a/doc/misc/cl.texi b/doc/misc/cl.texi index 2339d57..aa64ae2 100644 --- a/doc/misc/cl.texi +++ b/doc/misc/cl.texi @@ -3917,6 +3917,12 @@ Lists as Sets also appears in @var{list2}. @end defun address@hidden cl-set-equal list1 list2 @t{&key :test :key} +This function checks whether every element of @var{list1} also appears +in @var{list2} and if every element of @var{list2} also appears in address@hidden address@hidden defun + @node Association Lists @section Association Lists diff --git a/etc/NEWS b/etc/NEWS index 76c9dbc..e22a440 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -874,6 +874,9 @@ instead of its first. * Lisp Changes in Emacs 26.1 +** New function 'cl-set-equal' to check if every element of LIST1 also +appears in LIST2 and if every element of LIST2 also appears in LIST1. + +++ ** Emacs now supports records for user-defined types, via the new functions 'make-record', 'record', and 'recordp'. Records are now diff --git a/lisp/emacs-lisp/cl-seq.el b/lisp/emacs-lisp/cl-seq.el index 67ff1a0..db4a145 100644 --- a/lisp/emacs-lisp/cl-seq.el +++ b/lisp/emacs-lisp/cl-seq.el @@ -923,6 +923,16 @@ cl-subsetp (null cl-list1))))) ;;;###autoload +(defun cl-set-equal (cl-list1 cl-list2 &rest cl-keys) + "Return true if LIST1 and LIST2 have same elements. +I.e., if every element of LIST1 also appears in LIST2 and if +every element of LIST2 also appears in LIST1. +\nKeywords supported: :test :key \n(fn LIST1 LIST2 +[KEYWORD VALUE]...)" + (and (apply 'cl-subsetp cl-list1 cl-list2 cl-keys) + (apply 'cl-subsetp cl-list2 cl-list1 cl-keys))) + +;;;###autoload (defun cl-subst-if (cl-new cl-pred cl-tree &rest cl-keys) "Substitute NEW for elements matching PREDICATE in TREE (non-destructively). Return a copy of TREE with all matching elements replaced by NEW. diff --git a/test/lisp/emacs-lisp/cl-seq-tests.el b/test/lisp/emacs-lisp/cl-seq-tests.el index 61e3d72..0347ca4 100644 --- a/test/lisp/emacs-lisp/cl-seq-tests.el +++ b/test/lisp/emacs-lisp/cl-seq-tests.el @@ -292,6 +292,22 @@ cl-seq--with-side-effects (should (= 1 (cl-search (nthcdr 2 list) (nthcdr 2 list2)))) (should (= 3 (cl-search (nthcdr 2 list) list2))))) +;; keywords supported: :test :key +(ert-deftest cl-set-equal () + (should (cl-set-equal '(1 2 3) '(1 2 3))) + (should (cl-set-equal '(1 2 3) '(3 2 1))) + (should (cl-set-equal '(3 2 1) '(1 2 3))) + (should-not (cl-set-equal '(2 3) '(3 2 1))) + (should-not (cl-set-equal '(1 2 3) '(2 3))) + (should-not (cl-set-equal '("1" "2") '("2" "1") :test #'eq)) + (should (cl-set-equal '("1" "2") '("2" "1") :test #'equal)) + (should-not (cl-set-equal '(1 2) '(-1 -2))) + (should (cl-set-equal '(1 2) '(-1 -2) :key #'abs)) + (should-not (cl-set-equal '(("1" 1) ("2" 1)) '(("1" 2) ("2" 2)))) + (should-not (cl-set-equal '(("1" 1) ("2" 1)) '(("1" 2) ("2" 2)) :key #'car)) + (should-not (cl-set-equal '(("1" 1) ("2" 1)) '(("1" 2) ("2" 2)) :test #'equal)) + (should (cl-set-equal '(("1" 1) ("2" 1)) '(("1" 2) ("2" 2)) :key #'car :test #'equal))) + (ert-deftest cl-seq-test-bug24264 () "Test for http://debbugs.gnu.org/24264 ." (let ((list (append (make-list 8000005 1) '(8))) -- 2.9.3