[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Emacs-diffs] master 77fc272: Fix glitches introduced by nthcdr changes
From: |
Paul Eggert |
Subject: |
[Emacs-diffs] master 77fc272: Fix glitches introduced by nthcdr changes |
Date: |
Tue, 21 Aug 2018 05:05:37 -0400 (EDT) |
branch: master
commit 77fc2725985b4e5ef977ae6930835c7f0771c61c
Author: Paul Eggert <address@hidden>
Commit: Paul Eggert <address@hidden>
Fix glitches introduced by nthcdr changes
* src/fns.c (Fnthcdr): Fix recently-introduced bug when
nthcdr is supposed to yield a non-nil non-cons.
Reported by Glenn Morris and by Pip Cet here:
https://lists.gnu.org/r/emacs-devel/2018-08/msg00699.html
https://lists.gnu.org/r/emacs-devel/2018-08/msg00708.html
Speed up nthcdr for small N, as suggested by Pip Cet here:
https://lists.gnu.org/r/emacs-devel/2018-08/msg00707.html
* test/src/fns-tests.el (test-nthcdr-simple): New test.
---
src/fns.c | 35 +++++++++++++++++++++++++++--------
test/src/fns-tests.el | 5 +++++
2 files changed, 32 insertions(+), 8 deletions(-)
diff --git a/src/fns.c b/src/fns.c
index 8cff6b1..9d68101 100644
--- a/src/fns.c
+++ b/src/fns.c
@@ -1402,6 +1402,8 @@ DEFUN ("nthcdr", Fnthcdr, Snthcdr, 2, 2, 0,
doc: /* Take cdr N times on LIST, return the result. */)
(Lisp_Object n, Lisp_Object list)
{
+ Lisp_Object tail = list;
+
CHECK_INTEGER (n);
/* A huge but in-range EMACS_INT that can be substituted for a
@@ -1412,24 +1414,41 @@ DEFUN ("nthcdr", Fnthcdr, Snthcdr, 2, 2, 0,
EMACS_INT num;
if (FIXNUMP (n))
- num = XFIXNUM (n);
+ {
+ num = XFIXNUM (n);
+
+ /* Speed up small lists by omitting circularity and quit checking. */
+ if (num < 128)
+ {
+ for (; 0 < num; num--, tail = XCDR (tail))
+ if (! CONSP (tail))
+ {
+ CHECK_LIST_END (tail, list);
+ return Qnil;
+ }
+ return tail;
+ }
+ }
else
{
- num = mpz_sgn (XBIGNUM (n)->value);
- if (0 < num)
- num = large_num;
+ if (mpz_sgn (XBIGNUM (n)->value) < 0)
+ return tail;
+ num = large_num;
}
EMACS_INT tortoise_num = num;
- Lisp_Object tail = list, saved_tail = tail;
+ Lisp_Object saved_tail = tail;
FOR_EACH_TAIL_SAFE (tail)
{
- if (num <= 0)
- return tail;
- if (tail == li.tortoise)
+ /* If the tortoise just jumped (which is rare),
+ update TORTOISE_NUM accordingly. */
+ if (EQ (tail, li.tortoise))
tortoise_num = num;
+
saved_tail = XCDR (tail);
num--;
+ if (num == 0)
+ return saved_tail;
rarely_quit (num);
}
diff --git a/test/src/fns-tests.el b/test/src/fns-tests.el
index 92dc18f..b180f30 100644
--- a/test/src/fns-tests.el
+++ b/test/src/fns-tests.el
@@ -624,6 +624,11 @@
(should (eq (gethash b2 hash)
(funcall test b1 b2)))))))
+(ert-deftest test-nthcdr-simple ()
+ (should (eq (nthcdr 0 'x) 'x))
+ (should (eq (nthcdr 1 '(x . y)) 'y))
+ (should (eq (nthcdr 2 '(x y . z)) 'z)))
+
(ert-deftest test-nthcdr-circular ()
(dolist (len '(1 2 5 37 120 997 1024))
(let ((cycle (make-list len nil)))
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Emacs-diffs] master 77fc272: Fix glitches introduced by nthcdr changes,
Paul Eggert <=