diff options
author | Mattias EngdegÄrd <mattiase@acm.org> | 2022-07-13 13:46:52 +0200 |
---|---|---|
committer | Mattias EngdegÄrd <mattiase@acm.org> | 2022-07-17 17:35:49 +0200 |
commit | d62766305ad8fe6ca1695341c34b9836d051e3cb (patch) | |
tree | 3bb041d82a695bc4746d7c8f0fe79939ec80d0bc /src/fns.c | |
parent | 637436970f34f860d50f73a514b3bafd0c5cace7 (diff) | |
download | emacs-d62766305ad8fe6ca1695341c34b9836d051e3cb.tar.gz |
Add `take` and `ntake` (bug#56521)
These are useful list primitives, complementary to `nthcdr`.
* src/fns.c (Ftake, Fntake): New.
(syms_of_fns): Defsubr them.
* doc/lispref/lists.texi (List Elements):
* lisp/emacs-lisp/shortdoc.el (list): Document.
* lisp/emacs-lisp/byte-opt.el (side-effect-free-fns, pure-fns):
Declare `take` pure and side-effect-free.
* test/src/fns-tests.el (fns-tests--take-ref, fns--take-ntake):
New test.
* etc/NEWS: Announce.
Diffstat (limited to 'src/fns.c')
-rw-r--r-- | src/fns.c | 57 |
1 files changed, 57 insertions, 0 deletions
diff --git a/src/fns.c b/src/fns.c index 1f57e675b12..84cfec6c3f0 100644 --- a/src/fns.c +++ b/src/fns.c @@ -1557,6 +1557,61 @@ substring_both (Lisp_Object string, ptrdiff_t from, ptrdiff_t from_byte, return res; } +DEFUN ("take", Ftake, Stake, 2, 2, 0, + doc: /* Return the first N elements of LIST. +If N is zero or negative, return nil. +If LIST is no more than N elements long, return it (or a copy). */) + (Lisp_Object n, Lisp_Object list) +{ + CHECK_FIXNUM (n); + EMACS_INT m = XFIXNUM (n); + if (m <= 0) + return Qnil; + CHECK_LIST (list); + if (NILP (list)) + return Qnil; + Lisp_Object ret = Fcons (XCAR (list), Qnil); + Lisp_Object prev = ret; + m--; + list = XCDR (list); + while (m > 0 && CONSP (list)) + { + Lisp_Object p = Fcons (XCAR (list), Qnil); + XSETCDR (prev, p); + prev = p; + m--; + list = XCDR (list); + } + if (m > 0 && !NILP (list)) + wrong_type_argument (Qlistp, list); + return ret; +} + +DEFUN ("ntake", Fntake, Sntake, 2, 2, 0, + doc: /* Modify LIST to keep only the first N elements. +If N is zero or negative, return nil. +If LIST is no more than N elements long, return it. */) + (Lisp_Object n, Lisp_Object list) +{ + CHECK_FIXNUM (n); + EMACS_INT m = XFIXNUM (n); + if (m <= 0) + return Qnil; + CHECK_LIST (list); + Lisp_Object tail = list; + --m; + while (m > 0 && CONSP (tail)) + { + tail = XCDR (tail); + m--; + } + if (CONSP (tail)) + XSETCDR (tail, Qnil); + else if (!NILP (tail)) + wrong_type_argument (Qlistp, list); + return list; +} + DEFUN ("nthcdr", Fnthcdr, Snthcdr, 2, 2, 0, doc: /* Take cdr N times on LIST, return the result. */) (Lisp_Object n, Lisp_Object list) @@ -6082,6 +6137,8 @@ The same variable also affects the function `read-answer'. */); defsubr (&Scopy_alist); defsubr (&Ssubstring); defsubr (&Ssubstring_no_properties); + defsubr (&Stake); + defsubr (&Sntake); defsubr (&Snthcdr); defsubr (&Snth); defsubr (&Selt); |