From: Nicolas Petton Date: Tue, 14 Apr 2015 22:33:27 +0000 (+0200) Subject: Add seq-intersection and seq-difference to the seq library X-Git-Tag: emacs-25.0.90~2418 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=17d667b3876920652152baa4eab24134940a0f30;p=emacs.git Add seq-intersection and seq-difference to the seq library * lisp/emacs-lisp/seq.el (seq-intersection, seq-difference): New functions. * test/automated/seq-tests.el: Add tests for seq-intersection and seq-difference. * doc/lispref/sequences.texi: Add documentation for seq-intersection and seq-difference. --- diff --git a/doc/lispref/sequences.texi b/doc/lispref/sequences.texi index 1af353590cf..334b3478cb6 100644 --- a/doc/lispref/sequences.texi +++ b/doc/lispref/sequences.texi @@ -723,6 +723,35 @@ contain less elements than @var{n}. @var{n} must be an integer. If @end example @end defun +@defun seq-intersection sequence1 sequence2 &optional function + This function returns a list of the elements that appear both in +@var{sequence1} and @var{sequence2}. If the optional argument +@var{function} is non-@code{nil}, it is a function of two arguments to +use to compare elements instead of the default @code{equal}. + +@example +@group +(seq-intersection [2 3 4 5] [1 3 5 6 7]) +@result {} (3 5) +@end group +@end example +@end defun + + +@defun seq-difference sequence1 sequence2 &optional function + This function returns a list of the elements that appear in +@var{sequence1} but not in @var{sequence2}. If the optional argument +@var{function} is non-@code{nil}, it is a function of two arguments to +use to compare elements instead of the default @code{equal}. + +@example +@group +(seq-difference '(2 3 4 5) [1 3 5 6 7]) +@result {} (2 4) +@end group +@end example +@end defun + @defun seq-group-by function sequence This function separates the elements of @var{sequence} into an alist whose keys are the result of applying @var{function} to each element @@ -761,7 +790,6 @@ of type @var{type}. @var{type} can be one of the following symbols: @end example @end defun - @defmac seq-doseq (var sequence [result]) body@dots{} @cindex sequence iteration This macro is like @code{dolist}, except that @var{sequence} can be a list, diff --git a/lisp/emacs-lisp/seq.el b/lisp/emacs-lisp/seq.el index c5f5906e7e5..6f7f3c46e2a 100644 --- a/lisp/emacs-lisp/seq.el +++ b/lisp/emacs-lisp/seq.el @@ -4,7 +4,7 @@ ;; Author: Nicolas Petton ;; Keywords: sequences -;; Version: 1.3 +;; Version: 1.4 ;; Package: seq ;; Maintainer: emacs-devel@gnu.org @@ -240,6 +240,26 @@ negative integer or 0, nil is returned." (setq seq (seq-drop seq n))) (nreverse result)))) +(defun seq-intersection (seq1 seq2 &optional testfn) + "Return a list of the elements that appear in both SEQ1 and SEQ2. +Equality is defined by TESTFN if non-nil or by `equal' if nil." + (seq-reduce (lambda (acc elt) + (if (seq-contains-p seq2 elt testfn) + (cons elt acc) + acc)) + (seq-reverse seq1) + '())) + +(defun seq-difference (seq1 seq2 &optional testfn) + "Return a list of th elements that appear in SEQ1 but not in SEQ2. +Equality is defined by TESTFN if non-nil or by `equal' if nil." + (seq-reduce (lambda (acc elt) + (if (not (seq-contains-p seq2 elt testfn)) + (cons elt acc) + acc)) + (seq-reverse seq1) + '())) + (defun seq-group-by (function seq) "Apply FUNCTION to each element of SEQ. Separate the elements of SEQ into an alist using the results as @@ -318,6 +338,11 @@ This is an optimization for lists in `seq-take-while'." (setq n (+ 1 n))) n)) +(defun seq--activate-font-lock-keywords () + "Activate font-lock keywords for some symbols defined in seq." + (font-lock-add-keywords 'emacs-lisp-mode + '("\\"))) + (defalias 'seq-copy #'copy-sequence) (defalias 'seq-elt #'elt) (defalias 'seq-length #'length) @@ -325,5 +350,7 @@ This is an optimization for lists in `seq-take-while'." (defalias 'seq-each #'seq-do) (defalias 'seq-map #'mapcar) +(add-to-list 'emacs-lisp-mode-hook #'seq--activate-font-lock-keywords) + (provide 'seq) ;;; seq.el ends here diff --git a/test/automated/seq-tests.el b/test/automated/seq-tests.el index d3536b6f9a6..7f6e06cc4b6 100644 --- a/test/automated/seq-tests.el +++ b/test/automated/seq-tests.el @@ -250,5 +250,31 @@ Evaluate BODY for each created sequence. (should (same-contents-p list vector)) (should (vectorp vector)))) +(ert-deftest test-seq-intersection () + (let ((v1 [2 3 4 5]) + (v2 [1 3 5 6 7])) + (should (same-contents-p (seq-intersection v1 v2) + '(3 5)))) + (let ((l1 '(2 3 4 5)) + (l2 '(1 3 5 6 7))) + (should (same-contents-p (seq-intersection l1 l2) + '(3 5)))) + (let ((v1 [2 4 6]) + (v2 [1 3 5])) + (should (seq-empty-p (seq-intersection v1 v2))))) + +(ert-deftest test-seq-difference () + (let ((v1 [2 3 4 5]) + (v2 [1 3 5 6 7])) + (should (same-contents-p (seq-difference v1 v2) + '(2 4)))) + (let ((l1 '(2 3 4 5)) + (l2 '(1 3 5 6 7))) + (should (same-contents-p (seq-difference l1 l2) + '(2 4)))) + (let ((v1 [2 4 6]) + (v2 [2 4 6])) + (should (seq-empty-p (seq-difference v1 v2))))) + (provide 'seq-tests) ;;; seq-tests.el ends here