mirror of
https://git.savannah.gnu.org/git/emacs.git
synced 2024-12-18 10:16:51 +00:00
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.
This commit is contained in:
parent
eb83344fc7
commit
77fc272598
35
src/fns.c
35
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);
|
||||
}
|
||||
|
||||
|
@ -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)))
|
||||
|
Loading…
Reference in New Issue
Block a user