Function: nthcdr
nthcdr is a function defined in fns.c.
Signature
(nthcdr N LIST)
Documentation
Take cdr N times on LIST, return the result.
Other relevant functions are documented in the list group.
Probably introduced at or before Emacs version 30.1.
Shortdoc
;; list
(nthcdr 1 '(one two three))
=> (two three)
Aliases
Source Code
// Defined in /usr/src/emacs/src/fns.c
{
Lisp_Object tail = list;
CHECK_INTEGER (n);
/* A huge but in-range EMACS_INT that can be substituted for a
positive bignum while counting down. It does not introduce
miscounts because a list or cycle cannot possibly be this long,
and any counting error is fixed up later. */
EMACS_INT large_num = EMACS_INT_MAX;
EMACS_INT num;
if (FIXNUMP (n))
{
num = XFIXNUM (n);
/* Speed up small lists by omitting circularity and quit checking. */
if (num <= SMALL_LIST_LEN_MAX)
{
for (; 0 < num; num--, tail = XCDR (tail))
if (! CONSP (tail))
{
CHECK_LIST_END (tail, list);
return Qnil;
}
return tail;
}
}
else
{
if (mpz_sgn (*xbignum_val (n)) < 0)
return tail;
num = large_num;
}
EMACS_INT tortoise_num = num;
Lisp_Object saved_tail = tail;
FOR_EACH_TAIL_SAFE (tail)
{
/* If the tortoise just jumped (which is rare),
update TORTOISE_NUM accordingly. */
if (BASE_EQ (tail, li.tortoise))
tortoise_num = num;
saved_tail = XCDR (tail);
num--;
if (num == 0)
return saved_tail;
rarely_quit (num);
}
tail = saved_tail;
if (! CONSP (tail))
{
CHECK_LIST_END (tail, list);
return Qnil;
}
/* TAIL is part of a cycle. Reduce NUM modulo the cycle length to
avoid going around this cycle repeatedly. */
intptr_t cycle_length = tortoise_num - num;
if (! FIXNUMP (n))
{
/* Undo any error introduced when LARGE_NUM was substituted for
N, by adding N - LARGE_NUM to NUM, using arithmetic modulo
CYCLE_LENGTH. */
/* Add N mod CYCLE_LENGTH to NUM. */
if (cycle_length <= ULONG_MAX)
num += mpz_tdiv_ui (*xbignum_val (n), cycle_length);
else
{
mpz_set_intmax (mpz[0], cycle_length);
mpz_tdiv_r (mpz[0], *xbignum_val (n), mpz[0]);
intptr_t iz;
mpz_export (&iz, NULL, -1, sizeof iz, 0, 0, mpz[0]);
num += iz;
}
num += cycle_length - large_num % cycle_length;
}
num %= cycle_length;
/* One last time through the cycle. */
for (; 0 < num; num--)
{
tail = XCDR (tail);
rarely_quit (num);
}
return tail;
}