aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNicolas Petton2019-03-20 21:44:01 +0100
committerNicolas Petton2019-03-21 21:08:28 +0100
commit287cc58f39e9ca8f9ef31b31556f50c25feadaea (patch)
tree493af4f9d264395bba72ae15f0afa2162e135839
parent093d3e78d21d3d6c718997368ef4b31f9884401c (diff)
downloademacs-287cc58f39e9ca8f9ef31b31556f50c25feadaea.tar.gz
emacs-287cc58f39e9ca8f9ef31b31556f50c25feadaea.zip
New seq-contains-p predicate (Bug#34852)
* lisp/emacs-lisp/seq.el (seq-contains-p): New predicate function. It is a replacement for seq-contains which cannot be used as a predicate when a sequence contains nil values as it returns the element found. (seq-contains): Make obsolete. * test/lisp/emacs-lisp/seq-tests.el (test-seq-contains-p): (test-seq-intersection-with-nil, test-seq-set-equal-p-with-nil, test-difference-with-nil): Add regression tests. * doc/lispref/sequences.texi (Sequence Functions): Document seq-contains-p.
-rw-r--r--doc/lispref/sequences.texi9
-rw-r--r--lisp/emacs-lisp/seq.el20
-rw-r--r--test/lisp/emacs-lisp/seq-tests.el25
3 files changed, 45 insertions, 9 deletions
diff --git a/doc/lispref/sequences.texi b/doc/lispref/sequences.texi
index 0c3c4e3b282..a7f270c0680 100644
--- a/doc/lispref/sequences.texi
+++ b/doc/lispref/sequences.texi
@@ -782,10 +782,11 @@ before being sorted. @var{function} is a function of one argument.
782@end defun 782@end defun
783 783
784 784
785@defun seq-contains sequence elt &optional function 785@defun seq-contains-p sequence elt &optional function
786 This function returns the first element in @var{sequence} that is equal to 786 This function returns non-@code{nil} if at least one element in
787@var{elt}. If the optional argument @var{function} is non-@code{nil}, 787@var{sequence} is equal to @var{elt}. If the optional argument
788it is a function of two arguments to use instead of the default @code{equal}. 788@var{function} is non-@code{nil}, it is a function of two arguments to
789use instead of the default @code{equal}.
789 790
790@example 791@example
791@group 792@group
diff --git a/lisp/emacs-lisp/seq.el b/lisp/emacs-lisp/seq.el
index 4a811d78955..0b99b663ddc 100644
--- a/lisp/emacs-lisp/seq.el
+++ b/lisp/emacs-lisp/seq.el
@@ -356,6 +356,7 @@ found or not."
356 count)) 356 count))
357 357
358(cl-defgeneric seq-contains (sequence elt &optional testfn) 358(cl-defgeneric seq-contains (sequence elt &optional testfn)
359 (declare (obsolete seq-contains-p "27.1"))
359 "Return the first element in SEQUENCE that is equal to ELT. 360 "Return the first element in SEQUENCE that is equal to ELT.
360Equality is defined by TESTFN if non-nil or by `equal' if nil." 361Equality is defined by TESTFN if non-nil or by `equal' if nil."
361 (seq-some (lambda (e) 362 (seq-some (lambda (e)
@@ -363,11 +364,20 @@ Equality is defined by TESTFN if non-nil or by `equal' if nil."
363 e)) 364 e))
364 sequence)) 365 sequence))
365 366
367(cl-defgeneric seq-contains-p (sequence elt &optional testfn)
368 "Return non-nil if SEQUENCE contains an element equal to ELT.
369Equality is defined by TESTFN if non-nil or by `equal' if nil."
370 (catch 'seq--break
371 (seq-doseq (e sequence)
372 (when (funcall (or testfn #'equal) e elt)
373 (throw 'seq--break t)))
374 nil))
375
366(cl-defgeneric seq-set-equal-p (sequence1 sequence2 &optional testfn) 376(cl-defgeneric seq-set-equal-p (sequence1 sequence2 &optional testfn)
367 "Return non-nil if SEQUENCE1 and SEQUENCE2 contain the same elements, regardless of order. 377 "Return non-nil if SEQUENCE1 and SEQUENCE2 contain the same elements, regardless of order.
368Equality is defined by TESTFN if non-nil or by `equal' if nil." 378Equality is defined by TESTFN if non-nil or by `equal' if nil."
369 (and (seq-every-p (lambda (item1) (seq-contains sequence2 item1 testfn)) sequence1) 379 (and (seq-every-p (lambda (item1) (seq-contains-p sequence2 item1 testfn)) sequence1)
370 (seq-every-p (lambda (item2) (seq-contains sequence1 item2 testfn)) sequence2))) 380 (seq-every-p (lambda (item2) (seq-contains-p sequence1 item2 testfn)) sequence2)))
371 381
372(cl-defgeneric seq-position (sequence elt &optional testfn) 382(cl-defgeneric seq-position (sequence elt &optional testfn)
373 "Return the index of the first element in SEQUENCE that is equal to ELT. 383 "Return the index of the first element in SEQUENCE that is equal to ELT.
@@ -385,7 +395,7 @@ Equality is defined by TESTFN if non-nil or by `equal' if nil."
385TESTFN is used to compare elements, or `equal' if TESTFN is nil." 395TESTFN is used to compare elements, or `equal' if TESTFN is nil."
386 (let ((result '())) 396 (let ((result '()))
387 (seq-doseq (elt sequence) 397 (seq-doseq (elt sequence)
388 (unless (seq-contains result elt testfn) 398 (unless (seq-contains-p result elt testfn)
389 (setq result (cons elt result)))) 399 (setq result (cons elt result))))
390 (nreverse result))) 400 (nreverse result)))
391 401
@@ -410,7 +420,7 @@ negative integer or 0, nil is returned."
410 "Return a list of the elements that appear in both SEQUENCE1 and SEQUENCE2. 420 "Return a list of the elements that appear in both SEQUENCE1 and SEQUENCE2.
411Equality is defined by TESTFN if non-nil or by `equal' if nil." 421Equality is defined by TESTFN if non-nil or by `equal' if nil."
412 (seq-reduce (lambda (acc elt) 422 (seq-reduce (lambda (acc elt)
413 (if (seq-contains sequence2 elt testfn) 423 (if (seq-contains-p sequence2 elt testfn)
414 (cons elt acc) 424 (cons elt acc)
415 acc)) 425 acc))
416 (seq-reverse sequence1) 426 (seq-reverse sequence1)
@@ -420,7 +430,7 @@ Equality is defined by TESTFN if non-nil or by `equal' if nil."
420 "Return a list of the elements that appear in SEQUENCE1 but not in SEQUENCE2. 430 "Return a list of the elements that appear in SEQUENCE1 but not in SEQUENCE2.
421Equality is defined by TESTFN if non-nil or by `equal' if nil." 431Equality is defined by TESTFN if non-nil or by `equal' if nil."
422 (seq-reduce (lambda (acc elt) 432 (seq-reduce (lambda (acc elt)
423 (if (not (seq-contains sequence2 elt testfn)) 433 (if (not (seq-contains-p sequence2 elt testfn))
424 (cons elt acc) 434 (cons elt acc)
425 acc)) 435 acc))
426 (seq-reverse sequence1) 436 (seq-reverse sequence1)
diff --git a/test/lisp/emacs-lisp/seq-tests.el b/test/lisp/emacs-lisp/seq-tests.el
index d8f00cfea4c..ef05e2b389d 100644
--- a/test/lisp/emacs-lisp/seq-tests.el
+++ b/test/lisp/emacs-lisp/seq-tests.el
@@ -185,6 +185,18 @@ Evaluate BODY for each created sequence.
185 (with-test-sequences (seq '(3 4 5 6)) 185 (with-test-sequences (seq '(3 4 5 6))
186 (should (= 5 (seq-contains seq 5))))) 186 (should (= 5 (seq-contains seq 5)))))
187 187
188(ert-deftest test-seq-contains-p ()
189 (with-test-sequences (seq '(3 4 5 6))
190 (should (eq (seq-contains-p seq 3) t))
191 (should-not (seq-contains-p seq 7)))
192 (with-test-sequences (seq '())
193 (should-not (seq-contains-p seq 3))
194 (should-not (seq-contains-p seq nil))))
195
196(ert-deftest test-seq-contains-p-with-nil ()
197 (should (seq-contains-p [nil] nil))
198 (should (seq-contains-p '(nil) nil)))
199
188(ert-deftest test-seq-every-p () 200(ert-deftest test-seq-every-p ()
189 (with-test-sequences (seq '(43 54 22 1)) 201 (with-test-sequences (seq '(43 54 22 1))
190 (should (seq-every-p (lambda (elt) t) seq)) 202 (should (seq-every-p (lambda (elt) t) seq))
@@ -436,5 +448,18 @@ Evaluate BODY for each created sequence.
436 (should (equal (seq-rest lst) '(2 3))) 448 (should (equal (seq-rest lst) '(2 3)))
437 (should (equal (seq-rest vec) [2 3])))) 449 (should (equal (seq-rest vec) [2 3]))))
438 450
451;; Regression tests for bug#34852
452(progn
453 (ert-deftest test-seq-intersection-with-nil ()
454 (should (equal (seq-intersection '(1 2 nil) '(1 nil)) '(1 nil))))
455
456 (ert-deftest test-seq-set-equal-p-with-nil ()
457 (should (seq-set-equal-p '("a" "b" nil)
458 '(nil "b" "a"))))
459
460 (ert-deftest test-difference-with-nil ()
461 (should (equal (seq-difference '(1 nil) '(2 nil))
462 '(1)))))
463
439(provide 'seq-tests) 464(provide 'seq-tests)
440;;; seq-tests.el ends here 465;;; seq-tests.el ends here