]> git.eshelyaron.com Git - emacs.git/commitdiff
Add new function `seq-split'
authorLars Ingebrigtsen <larsi@gnus.org>
Sun, 3 Jul 2022 10:55:00 +0000 (12:55 +0200)
committerLars Ingebrigtsen <larsi@gnus.org>
Sun, 3 Jul 2022 10:55:00 +0000 (12:55 +0200)
* doc/lispref/sequences.texi (Sequence Functions): Document it.

* lisp/emacs-lisp/seq.el (seq-split): New function.

* lisp/emacs-lisp/shortdoc.el (sequence): Mention it.

doc/lispref/sequences.texi
etc/NEWS
lisp/emacs-lisp/seq.el
lisp/emacs-lisp/shortdoc.el
test/lisp/emacs-lisp/seq-tests.el

index c3f4cff301528aac7b897ca4bdb0335825eb8f57..39230d0adc4de7548855b44e7971936f4930cf16 100644 (file)
@@ -577,6 +577,20 @@ starting from the first one for which @var{predicate} returns @code{nil}.
 @end example
 @end defun
 
+@defun seq-split sequence length
+  This function returns a list consisting of sub-sequences of
+@var{sequence} of (at most) length @var{length}.  (The final element
+may be shorter than @var{length} if the length of @var{sequence} isn't
+a multiple of @var{length}.
+
+@example
+@group
+(seq-split [0 1 2 3 4] 2)
+@result{} ([0 1] [2 3] [4])
+@end group
+@end example
+@end defun
+
 @defun seq-do function sequence
   This function applies @var{function} to each element of
 @var{sequence} in turn (presumably for side effects), and returns
index af3240e5046fabbabd8345ceb2995b1e0a5c6356..e1cdbd5077aff85b32906dc436e63f311eb6d127 100644 (file)
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -2250,6 +2250,10 @@ patcomp.el, pc-mode.el, pc-select.el, s-region.el, and sregex.el.
 \f
 * Lisp Changes in Emacs 29.1
 
++++
+** New function 'seq-split'.
+This returns a list of sub-sequences of the specified sequence.
+
 +++
 ** 'plist-get', 'plist-put' and 'plist-member' are no longer limited to 'eq'.
 These function now take an optional comparison predicate argument.
index 947b64e86870d7f2801b69786c3c35f220db620c..36c17f4cd5eae192da0a9d4638a7a2cabea74664 100644 (file)
@@ -632,5 +632,20 @@ Signal an error if SEQUENCE is empty."
   ;; we automatically highlight macros.
   (add-hook 'emacs-lisp-mode-hook #'seq--activate-font-lock-keywords))
 
+(defun seq-split (sequence length)
+  "Split SEQUENCE into a list of sub-sequences of at most LENGTH.
+All the sub-sequences will be of LENGTH, except the last one,
+which may be shorter."
+  (when (< length 1)
+    (error "Sub-sequence length must be larger than zero"))
+  (let ((result nil)
+        (seq-length (length sequence))
+        (start 0))
+    (while (< start seq-length)
+      (push (seq-subseq sequence start
+                        (setq start (min seq-length (+ start length))))
+            result))
+    (nreverse result)))
+
 (provide 'seq)
 ;;; seq.el ends here
index c82aa3365cd95ffd79fa883f2c53d432e5723ab3..f53e783111c38b47cf2b2ea9fddce39faa471557 100644 (file)
@@ -889,6 +889,8 @@ A FUNC form can have any number of `:no-eval' (or `:no-value'),
    :eval (seq-subseq '(a b c d e) 2 4))
   (seq-take
    :eval (seq-take '(a b c d e) 3))
+  (seq-split
+   :eval (seq-split [0 1 2 3 5] 2))
   (seq-take-while
    :eval (seq-take-while #'cl-evenp [2 4 9 6 5]))
   (seq-uniq
index 9e5d59163f9b270a2776f48cddc08d8f4cbcc5a4..d979604910e7dc1e15aa38c5239e82daeefee3ee 100644 (file)
@@ -511,5 +511,26 @@ Evaluate BODY for each created sequence.
     (should (equal (seq-difference '(1 nil) '(2 nil))
                    '(1)))))
 
+(ert-deftest test-seq-split ()
+  (let ((seq [0 1 2 3 4 5 6 7 8 9 10]))
+    (should (equal seq (car (seq-split seq 20))))
+    (should (equal seq (car (seq-split seq 11))))
+    (should (equal (seq-split seq 10)
+                   '([0 1 2 3 4 5 6 7 8 9] [10])))
+    (should (equal (seq-split seq 5)
+                   '([0 1 2 3 4] [5 6 7 8 9] [10])))
+    (should (equal (seq-split seq 1)
+                   '([0] [1] [2] [3] [4] [5] [6] [7] [8] [9] [10])))
+    (should-error (seq-split seq 0))
+    (should-error (seq-split seq -10)))
+  (let ((seq '(0 1 2 3 4 5 6 7 8 9)))
+    (should (equal (seq-split seq 5)
+                   '((0 1 2 3 4) (5 6 7 8 9)))))
+  (let ((seq "0123456789"))
+    (should (equal (seq-split seq 2)
+                   '("01" "23" "45" "67" "89")))
+    (should (equal (seq-split seq 3)
+                   '("012" "345" "678" "9")))))
+
 (provide 'seq-tests)
 ;;; seq-tests.el ends here