all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
From: Okamsn via "Bug reports for GNU Emacs, the Swiss army knife of text editors" <bug-gnu-emacs@gnu.org>
To: 67456@debbugs.gnu.org, nicolas@petton.fr
Subject: bug#67456: [PATCH] seq.el: Add functions for mapping over subsequences
Date: Tue, 28 Nov 2023 01:29:14 +0000	[thread overview]
Message-ID: <3f57efba-4258-4c81-8c57-e6bedd19888f@protonmail.com> (raw)
In-Reply-To: <6f6d9f2d-fee9-4d1d-a1e4-8c6ce57a0627@protonmail.com>

[-- Attachment #1: Type: text/plain, Size: 1069 bytes --]

Okamsn wrote:
> Hello,
> 
> The attached features work like `cl-maplist` and `cl-mapl`, applying
> functions to a sequence and to the remaining parts of a sequence.  For
> example, `(seq-mapsub #'identity [1 2 3])` returns `([1 2 3] [2 3] [3])`.
> 
> The patch adds a `seq-mapsub`, `seq-dosub`, and a `seq-doseqsub`,
> similar to `seq-map`, `seq-do`, and `seq-doseq`, respectively.
> 
> I was looking for an equivalent for vectors of `cl-maplist`, `cl-mapl`,
> and `cl-loop`'s `for VAR on LIST`, and think that these would be useful
> additions.
> 
> To get the sub-sequences, the code uses `seq-rest` and stops when the
> returned sub-sequence is empty according to `seq-empty-p`.  This is
> similar to how I would do it for a list, using `cdr` and `null`, but is
> that a good way to do it for arrays and other sequences?
> 
> Thank you.

I've updated the patch to only add the one `seq-mapsub` function, to be 
more like `seq-mapn` and `seq-mapcat`, and to add an optimized version 
for lists.

Would you like anything changed?

Thank you.

[-- Attachment #2: v2-0001-Create-function-seq-mapsub-for-mapping-over-subse.patch --]
[-- Type: text/x-patch, Size: 4132 bytes --]

From ea8ee51977c0a583bc374856af633945144bc7dd Mon Sep 17 00:00:00 2001
From: Earl Hyatt <okamsn@protonmail.com>
Date: Sun, 26 Nov 2023 11:20:28 -0500
Subject: [PATCH v2] Create function 'seq-mapsub' for mapping over
 subsequences.

This function is similar to 'cl-maplist'.

* lisp/emacs-lisp/seq.el (seq-mapsub): Add generic function for
mapping over sub-sequences, like in 'cl-maplist'.  Add optimized
implementation for lists.

* test/lisp/emacs-lisp/seq-tests.el (test-seq-mapsub): Add tests for
the above functions.

* doc/lispref/sequences.texi (Sequence Functions): Describe the
function.
---
 doc/lispref/sequences.texi        | 20 ++++++++++++++++++++
 lisp/emacs-lisp/seq.el            | 25 +++++++++++++++++++++++++
 test/lisp/emacs-lisp/seq-tests.el | 10 ++++++++++
 3 files changed, 55 insertions(+)

diff --git a/doc/lispref/sequences.texi b/doc/lispref/sequences.texi
index c9c6bb31350..1234f51e188 100644
--- a/doc/lispref/sequences.texi
+++ b/doc/lispref/sequences.texi
@@ -644,6 +644,26 @@ Sequence Functions
 @end example
 @end defun
 
+@defun seq-mapsub function sequence
+  This function returns the result of applying @var{function} to
+@var{sequence} and its sub-sequences.  The first sequence used is
+@var{sequence}, the second sequence used is everything in
+@var{sequence} after the first element, the third sequence used is
+everything after the second element, and so on. The returned value is
+a list. If @var{sequence} is empty, then the returned list is empty.
+
+@example
+@group
+(seq-mapsub #'identity [1 2 3])
+@result{} ([1 2 3] [2 3] [3])
+@end group
+@group
+(seq-mapsub #'identity [])
+@result{} nil
+@end group
+@end example
+@end defun
+
 @defun seq-filter predicate sequence
 @cindex filtering sequences
   This function returns a list of all the elements in @var{sequence}
diff --git a/lisp/emacs-lisp/seq.el b/lisp/emacs-lisp/seq.el
index 346250c1d35..e9421d7a5db 100644
--- a/lisp/emacs-lisp/seq.el
+++ b/lisp/emacs-lisp/seq.el
@@ -235,6 +235,22 @@ seq-mapn
       (setq sequences (seq-map #'cdr sequences)))
     (nreverse result)))
 
+(cl-defgeneric seq-mapsub (function sequence)
+  "Return the result of applying FUNCTION to SEQUENCE and its sub-sequences.
+
+If SEQUENCE is empty, nil is returned.
+
+The first sequence used is SEQUENCE, the second sequence used is
+everything in SEQUENCE after the first element, the third
+sequence used is everything after the second element, and so
+on."
+  (let ((result nil))
+    (while (not (seq-empty-p sequence))
+      (push (funcall function sequence)
+            result)
+      (setq sequence (seq-rest sequence)))
+    (nreverse result)))
+
 (cl-defgeneric seq-drop (sequence n)
   "Remove the first N elements of SEQUENCE and return the resulting sequence.
 The result is a sequence of the same type as SEQUENCE.
@@ -671,6 +687,15 @@ seq-drop-while
 (cl-defmethod seq-empty-p ((list list))
   "Optimized implementation of `seq-empty-p' for lists."
   (null list))
+
+(cl-defmethod seq-mapsub (function (list list))
+  "Optimized implementation of `seq-mapsub' for lists."
+  (let ((result nil))
+    (while list
+      (push (funcall function list)
+            result)
+      (setq list (cdr list)))
+    (nreverse result)))
 \f
 
 (defun seq--into-list (sequence)
diff --git a/test/lisp/emacs-lisp/seq-tests.el b/test/lisp/emacs-lisp/seq-tests.el
index 71ff991c215..fa6f9efa762 100644
--- a/test/lisp/emacs-lisp/seq-tests.el
+++ b/test/lisp/emacs-lisp/seq-tests.el
@@ -121,6 +121,16 @@ test-seq-do-indexed
       (should (equal (seq-elt result 1) '(5 1)))
       (should (equal (seq-elt result 2) '(4 0))))))
 
+(ert-deftest test-seq-mapsub ()
+  (should (equal (seq-mapsub #'identity [1 2 3])
+                 '([1 2 3] [2 3] [3])))
+  (should (equal (seq-mapsub #'identity '(1 2 3))
+                 '((1 2 3) (2 3) (3))))
+  (should (equal (seq-mapsub #'identity nil)
+                 nil))
+  (should (equal (seq-mapsub #'identity [])
+                 nil)))
+
 (ert-deftest test-seq-filter ()
   (with-test-sequences (seq '(6 7 8 9 10))
     (should (equal (seq-filter #'test-sequences-evenp seq) '(6 8 10)))
-- 
2.34.1


  reply	other threads:[~2023-11-28  1:29 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-11-26 17:17 bug#67456: [PATCH] seq.el: Add functions for mapping over subsequences Okamsn via Bug reports for GNU Emacs, the Swiss army knife of text editors
2023-11-28  1:29 ` Okamsn via Bug reports for GNU Emacs, the Swiss army knife of text editors [this message]
2023-12-01 20:14   ` Augusto Stoffel
2023-12-03  1:25     ` Okamsn via Bug reports for GNU Emacs, the Swiss army knife of text editors
2023-12-25 20:26 ` Philip Kaludercic

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=3f57efba-4258-4c81-8c57-e6bedd19888f@protonmail.com \
    --to=bug-gnu-emacs@gnu.org \
    --cc=67456@debbugs.gnu.org \
    --cc=nicolas@petton.fr \
    --cc=okamsn@protonmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this external index

	https://git.savannah.gnu.org/cgit/emacs.git
	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.