defconst, defvar: proclaim special at compile-time
[bpt/guile.git] / libguile / list.c
CommitLineData
fc8a9004
MW
1/* Copyright (C) 1995-1997, 2000, 2001, 2003, 2004, 2008-2011,
2 * 2014 Free Software Foundation, Inc.
0f2d19dd 3 *
73be1d9e 4 * This library is free software; you can redistribute it and/or
53befeb7
NJ
5 * modify it under the terms of the GNU Lesser General Public License
6 * as published by the Free Software Foundation; either version 3 of
7 * the License, or (at your option) any later version.
0f2d19dd 8 *
53befeb7
NJ
9 * This library is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
73be1d9e
MV
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
0f2d19dd 13 *
73be1d9e
MV
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
53befeb7
NJ
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 * 02110-1301 USA
73be1d9e 18 */
1bbd0b84 19
1bbd0b84 20
0f2d19dd 21\f
dbb605f5
LC
22#ifdef HAVE_CONFIG_H
23# include <config.h>
24#endif
25
a0599745
MD
26#include "libguile/_scm.h"
27#include "libguile/eq.h"
20e6290e 28
a0599745
MD
29#include "libguile/validate.h"
30#include "libguile/list.h"
c614a00b 31#include "libguile/eval.h"
0f2d19dd 32
0f2d19dd 33#include <stdarg.h>
0f2d19dd
JB
34
35\f
df13742c 36/* creating lists */
0f2d19dd 37
b2b33168
AW
38#define SCM_I_CONS(cell, x, y) \
39 do { \
40 cell = scm_cell (SCM_UNPACK (x), SCM_UNPACK (y)); \
41 } while (0)
1afff620
KN
42
43SCM
44scm_list_1 (SCM e1)
45{
46 SCM c1;
47 SCM_I_CONS (c1, e1, SCM_EOL);
48 return c1;
49}
50
51SCM
52scm_list_2 (SCM e1, SCM e2)
53{
54 SCM c1, c2;
55 SCM_I_CONS (c2, e2, SCM_EOL);
56 SCM_I_CONS (c1, e1, c2);
57 return c1;
58}
59
60SCM
61scm_list_3 (SCM e1, SCM e2, SCM e3)
62{
63 SCM c1, c2, c3;
64 SCM_I_CONS (c3, e3, SCM_EOL);
65 SCM_I_CONS (c2, e2, c3);
66 SCM_I_CONS (c1, e1, c2);
67 return c1;
68}
69
70SCM
71scm_list_4 (SCM e1, SCM e2, SCM e3, SCM e4)
72{
73 return scm_cons2 (e1, e2, scm_list_2 (e3, e4));
74}
75
76SCM
77scm_list_5 (SCM e1, SCM e2, SCM e3, SCM e4, SCM e5)
78{
79 return scm_cons2 (e1, e2, scm_list_3 (e3, e4, e5));
80}
81
0f2d19dd 82SCM
1afff620 83scm_list_n (SCM elt, ...)
0f2d19dd
JB
84{
85 va_list foo;
2de14ecd
GB
86 SCM answer = SCM_EOL;
87 SCM *pos = &answer;
0f2d19dd 88
0dbfb25a 89 va_start (foo, elt);
fbd485ba 90 while (! SCM_UNBNDP (elt))
0f2d19dd 91 {
1e55d288 92#if (SCM_DEBUG_CELL_ACCESSES == 1)
8c5bb729 93 if (SCM_HEAP_OBJECT_P (elt))
eb741d98 94 SCM_VALIDATE_CELL(elt, 0);
1e55d288 95#endif
0f2d19dd 96 *pos = scm_cons (elt, SCM_EOL);
25d8012c 97 pos = SCM_CDRLOC (*pos);
0f2d19dd
JB
98 elt = va_arg (foo, SCM);
99 }
de90ef0f 100 va_end (foo);
0f2d19dd
JB
101 return answer;
102}
103
104
2ac6b60e
KR
105SCM_DEFINE (scm_make_list, "make-list", 1, 1, 0,
106 (SCM n, SCM init),
107 "Create a list containing of @var{n} elements, where each\n"
108 "element is initialized to @var{init}. @var{init} defaults to\n"
109 "the empty list @code{()} if not given.")
661ae7ab 110#define FUNC_NAME s_scm_make_list
2ac6b60e
KR
111{
112 unsigned nn = scm_to_uint (n);
113 unsigned i;
114 SCM ret = SCM_EOL;
115
116 if (SCM_UNBNDP (init))
117 init = SCM_EOL;
118
119 for (i = 0; i < nn; i++)
120 ret = scm_cons (init, ret);
121 return ret;
122}
123#undef FUNC_NAME
124
125
b906b056 126SCM_DEFINE (scm_cons_star, "cons*", 1, 0, 1,
1bbd0b84 127 (SCM arg, SCM rest),
5352393c
MG
128 "Like @code{list}, but the last arg provides the tail of the\n"
129 "constructed list, returning @code{(cons @var{arg1} (cons\n"
a17bb5fd 130 "@var{arg2} (cons @dots{} @var{argn})))}. Requires at least one\n"
5352393c
MG
131 "argument. If given one argument, that argument is returned as\n"
132 "result. This function is called @code{list*} in some other\n"
133 "Schemes and in Common LISP.")
26a379b2 134#define FUNC_NAME s_scm_cons_star
a610b8d9 135{
b906b056
KR
136 SCM ret = SCM_EOL;
137 SCM *p = &ret;
138
af45e3b0 139 SCM_VALIDATE_REST_ARGUMENT (rest);
b906b056
KR
140
141 for ( ; scm_is_pair (rest); rest = SCM_CDR (rest))
a610b8d9 142 {
b906b056
KR
143 *p = scm_cons (arg, SCM_EOL);
144 p = SCM_CDRLOC (*p);
145 arg = SCM_CAR (rest);
a610b8d9 146 }
b906b056
KR
147
148 *p = arg;
149 return ret;
a610b8d9 150}
1bbd0b84 151#undef FUNC_NAME
a610b8d9 152
0f2d19dd
JB
153
154\f
df13742c 155/* general questions about lists --- null?, list?, length, etc. */
0f2d19dd 156
3b3b36dd 157SCM_DEFINE (scm_null_p, "null?", 1, 0, 0,
1bbd0b84 158 (SCM x),
5352393c 159 "Return @code{#t} iff @var{x} is the empty list, else @code{#f}.")
1bbd0b84 160#define FUNC_NAME s_scm_null_p
0f2d19dd 161{
7888309b 162 return scm_from_bool (SCM_NULL_OR_NIL_P (x));
0f2d19dd 163}
1bbd0b84 164#undef FUNC_NAME
0f2d19dd 165
2de14ecd 166
3b3b36dd 167SCM_DEFINE (scm_list_p, "list?", 1, 0, 0,
1bbd0b84 168 (SCM x),
5352393c 169 "Return @code{#t} iff @var{x} is a proper list, else @code{#f}.")
1bbd0b84 170#define FUNC_NAME s_scm_list_p
0f2d19dd 171{
7888309b 172 return scm_from_bool (scm_ilength (x) >= 0);
0f2d19dd 173}
1bbd0b84 174#undef FUNC_NAME
0f2d19dd
JB
175
176
df13742c 177/* Return the length of SX, or -1 if it's not a proper list.
448a3bc2 178 This uses the "tortoise and hare" algorithm to detect "infinitely
df13742c
JB
179 long" lists (i.e. lists with cycles in their cdrs), and returns -1
180 if it does find one. */
c014a02e 181long
fc8a9004 182scm_ilength (SCM sx)
0f2d19dd 183{
c014a02e 184 long i = 0;
e1385ffc
GB
185 SCM tortoise = sx;
186 SCM hare = sx;
df13742c 187
fc8a9004
MW
188 do
189 {
190 if (!scm_is_pair (hare))
191 return SCM_NULL_OR_NIL_P (hare) ? i : -1;
192 hare = SCM_CDR (hare);
193 i++;
194 if (!scm_is_pair (hare))
195 return SCM_NULL_OR_NIL_P (hare) ? i : -1;
196 hare = SCM_CDR (hare);
197 i++;
198 /* For every two steps the hare takes, the tortoise takes one. */
199 tortoise = SCM_CDR (tortoise);
200 }
bc36d050 201 while (!scm_is_eq (hare, tortoise));
df13742c 202
448a3bc2 203 /* If the tortoise ever catches the hare, then the list must contain
df13742c 204 a cycle. */
0f2d19dd
JB
205 return -1;
206}
207
2de14ecd 208
3b3b36dd 209SCM_DEFINE (scm_length, "length", 1, 0, 0,
1bbd0b84 210 (SCM lst),
5352393c 211 "Return the number of elements in list @var{lst}.")
1bbd0b84 212#define FUNC_NAME s_scm_length
0f2d19dd 213{
c014a02e 214 long i;
34d19ef6 215 SCM_VALIDATE_LIST_COPYLEN (1, lst, i);
e11e83f3 216 return scm_from_long (i);
0f2d19dd 217}
1bbd0b84 218#undef FUNC_NAME
0f2d19dd
JB
219
220
221\f
df13742c 222/* appending lists */
0f2d19dd 223
a1ec6916 224SCM_DEFINE (scm_append, "append", 0, 0, 1,
1bbd0b84 225 (SCM args),
5352393c
MG
226 "Return a list consisting of the elements the lists passed as\n"
227 "arguments.\n"
1e6808ea 228 "@lisp\n"
5352393c
MG
229 "(append '(x) '(y)) @result{} (x y)\n"
230 "(append '(a) '(b c d)) @result{} (a b c d)\n"
231 "(append '(a (b)) '((c))) @result{} (a (b) (c))\n"
1e6808ea 232 "@end lisp\n"
5352393c
MG
233 "The resulting list is always newly allocated, except that it\n"
234 "shares structure with the last list argument. The last\n"
235 "argument may actually be any object; an improper list results\n"
236 "if the last argument is not a proper list.\n"
1e6808ea 237 "@lisp\n"
5352393c
MG
238 "(append '(a b) '(c . d)) @result{} (a b c . d)\n"
239 "(append '() 'a) @result{} a\n"
1e6808ea 240 "@end lisp")
1bbd0b84 241#define FUNC_NAME s_scm_append
0f2d19dd 242{
af45e3b0 243 SCM_VALIDATE_REST_ARGUMENT (args);
d2e53ed6 244 if (scm_is_null (args)) {
af45e3b0
DH
245 return SCM_EOL;
246 } else {
247 SCM res = SCM_EOL;
248 SCM *lloc = &res;
249 SCM arg = SCM_CAR (args);
4c13270f 250 int argnum = 1;
af45e3b0 251 args = SCM_CDR (args);
d2e53ed6
MV
252 while (!scm_is_null (args)) {
253 while (scm_is_pair (arg)) {
af45e3b0
DH
254 *lloc = scm_cons (SCM_CAR (arg), SCM_EOL);
255 lloc = SCM_CDRLOC (*lloc);
256 arg = SCM_CDR (arg);
257 }
4c13270f 258 SCM_VALIDATE_NULL_OR_NIL (argnum, arg);
af45e3b0
DH
259 arg = SCM_CAR (args);
260 args = SCM_CDR (args);
4c13270f 261 argnum++;
af45e3b0
DH
262 };
263 *lloc = arg;
0f2d19dd
JB
264 return res;
265 }
0f2d19dd 266}
1bbd0b84 267#undef FUNC_NAME
0f2d19dd
JB
268
269
a1ec6916 270SCM_DEFINE (scm_append_x, "append!", 0, 0, 1,
226a56a3 271 (SCM args),
1e6808ea 272 "A destructive version of @code{append} (@pxref{Pairs and\n"
7a095584 273 "Lists,,,r5rs, The Revised^5 Report on Scheme}). The cdr field\n"
1e6808ea 274 "of each list's final pair is changed to point to the head of\n"
71a89639 275 "the next list, so no consing is performed. Return\n"
1e6808ea 276 "the mutated list.")
1bbd0b84 277#define FUNC_NAME s_scm_append_x
0f2d19dd 278{
d4641098 279 SCM ret, *loc;
226a56a3
MW
280 int argnum = 1;
281 SCM_VALIDATE_REST_ARGUMENT (args);
d4641098 282
226a56a3 283 if (scm_is_null (args))
d4641098
KR
284 return SCM_EOL;
285
286 loc = &ret;
287 for (;;)
288 {
226a56a3 289 SCM arg = SCM_CAR (args);
d4641098
KR
290 *loc = arg;
291
226a56a3
MW
292 args = SCM_CDR (args);
293 if (scm_is_null (args))
d4641098
KR
294 return ret;
295
296 if (!SCM_NULL_OR_NIL_P (arg))
297 {
226a56a3 298 SCM_VALIDATE_CONS (argnum, arg);
d4641098 299 loc = SCM_CDRLOC (scm_last_pair (arg));
226a56a3 300 SCM_VALIDATE_NULL_OR_NIL (argnum, *loc);
d4641098 301 }
226a56a3 302 argnum++;
af45e3b0 303 }
0f2d19dd 304}
1bbd0b84 305#undef FUNC_NAME
0f2d19dd
JB
306
307
3b3b36dd 308SCM_DEFINE (scm_last_pair, "last-pair", 1, 0, 0,
e1385ffc 309 (SCM lst),
71a89639 310 "Return the last pair in @var{lst}, signalling an error if\n"
b380b885 311 "@var{lst} is circular.")
1bbd0b84 312#define FUNC_NAME s_scm_last_pair
df13742c 313{
e1385ffc
GB
314 SCM tortoise = lst;
315 SCM hare = lst;
0f2d19dd 316
c96d76b8
NJ
317 if (SCM_NULL_OR_NIL_P (lst))
318 return lst;
df13742c 319
e1385ffc
GB
320 SCM_VALIDATE_CONS (SCM_ARG1, lst);
321 do {
322 SCM ahead = SCM_CDR(hare);
d2e53ed6 323 if (!scm_is_pair (ahead)) return hare;
e1385ffc
GB
324 hare = ahead;
325 ahead = SCM_CDR(hare);
d2e53ed6 326 if (!scm_is_pair (ahead)) return hare;
e1385ffc
GB
327 hare = ahead;
328 tortoise = SCM_CDR(tortoise);
df13742c 329 }
bc36d050 330 while (!scm_is_eq (hare, tortoise));
1afff620 331 SCM_MISC_ERROR ("Circular structure in position 1: ~S", scm_list_1 (lst));
df13742c 332}
1bbd0b84 333#undef FUNC_NAME
df13742c
JB
334
335\f
336/* reversing lists */
0f2d19dd 337
a1ec6916 338SCM_DEFINE (scm_reverse, "reverse", 1, 0, 0,
e1385ffc 339 (SCM lst),
5352393c
MG
340 "Return a new list that contains the elements of @var{lst} but\n"
341 "in reverse order.")
e1385ffc
GB
342#define FUNC_NAME s_scm_reverse
343{
344 SCM result = SCM_EOL;
345 SCM tortoise = lst;
346 SCM hare = lst;
347
348 do {
c96d76b8 349 if (SCM_NULL_OR_NIL_P(hare)) return result;
d2e53ed6 350 SCM_ASSERT(scm_is_pair(hare), lst, 1, FUNC_NAME);
e1385ffc
GB
351 result = scm_cons (SCM_CAR (hare), result);
352 hare = SCM_CDR (hare);
c96d76b8 353 if (SCM_NULL_OR_NIL_P(hare)) return result;
d2e53ed6 354 SCM_ASSERT(scm_is_pair(hare), lst, 1, FUNC_NAME);
e1385ffc
GB
355 result = scm_cons (SCM_CAR (hare), result);
356 hare = SCM_CDR (hare);
357 tortoise = SCM_CDR (tortoise);
358 }
bc36d050 359 while (!scm_is_eq (hare, tortoise));
1afff620 360 SCM_MISC_ERROR ("Circular structure in position 1: ~S", scm_list_1 (lst));
e1385ffc
GB
361}
362#undef FUNC_NAME
363
364SCM_DEFINE (scm_reverse_x, "reverse!", 1, 1, 0,
365 (SCM lst, SCM new_tail),
7a095584
NJ
366 "A destructive version of @code{reverse} (@pxref{Pairs and Lists,,,r5rs,\n"
367 "The Revised^5 Report on Scheme}). The cdr of each cell in @var{lst} is\n"
71a89639
MV
368 "modified to point to the previous list element. Return the\n"
369 "reversed list.\n\n"
b380b885
MD
370 "Caveat: because the list is modified in place, the tail of the original\n"
371 "list now becomes its head, and the head of the original list now becomes\n"
372 "the tail. Therefore, the @var{lst} symbol to which the head of the\n"
373 "original list was bound now points to the tail. To ensure that the head\n"
374 "of the modified list is not lost, it is wise to save the return value of\n"
375 "@code{reverse!}")
1bbd0b84 376#define FUNC_NAME s_scm_reverse_x
0f2d19dd 377{
0ece4850
DK
378 SCM old_lst = lst;
379 SCM tail = SCM_BOOL_F;
380
3946f0de
MD
381 if (SCM_UNBNDP (new_tail))
382 new_tail = SCM_EOL;
0f2d19dd 383
0ece4850
DK
384 if (SCM_NULL_OR_NIL_P (lst))
385 return new_tail;
386
387 /* SCM_VALIDATE_LIST would run through the whole list to make sure it
388 is not eventually circular. In contrast to most list operations,
389 reverse! cannot get stuck in an infinite loop but arrives back at
390 the start when given an eventually or fully circular list. Because
391 of that, we can save the cost of an upfront proper list check at
392 the price of having to do a double reversal in the error case.
393 */
394
395 while (scm_is_pair (lst))
3946f0de 396 {
e1385ffc 397 SCM old_tail = SCM_CDR (lst);
0ece4850
DK
398 SCM_SETCDR (lst, tail);
399 tail = lst;
e1385ffc 400 lst = old_tail;
3946f0de 401 }
0ece4850
DK
402
403 if (SCM_LIKELY (SCM_NULL_OR_NIL_P (lst)))
404 {
405 SCM_SETCDR (old_lst, new_tail);
406 return tail;
407 }
408
409 /* We did not start with a proper list. Undo the reversal. */
410
411 while (scm_is_pair (tail))
412 {
413 SCM old_tail = SCM_CDR (tail);
414 SCM_SETCDR (tail, lst);
415 lst = tail;
416 tail = old_tail;
417 }
418
419 SCM_WRONG_TYPE_ARG (1, lst);
420 return lst;
0f2d19dd 421}
1bbd0b84 422#undef FUNC_NAME
0f2d19dd 423
0f2d19dd 424\f
685c0d71 425
df13742c 426/* indexing lists by element number */
0f2d19dd 427
3b3b36dd 428SCM_DEFINE (scm_list_ref, "list-ref", 2, 0, 0,
685c0d71 429 (SCM list, SCM k),
5352393c 430 "Return the @var{k}th element from @var{list}.")
1bbd0b84
GB
431#define FUNC_NAME s_scm_list_ref
432{
685c0d71 433 SCM lst = list;
c014a02e 434 unsigned long int i;
a55c2b68 435 i = scm_to_ulong (k);
d2e53ed6 436 while (scm_is_pair (lst)) {
685c0d71
DH
437 if (i == 0)
438 return SCM_CAR (lst);
439 else {
440 --i;
441 lst = SCM_CDR (lst);
442 }
443 };
c96d76b8 444 if (SCM_NULL_OR_NIL_P (lst))
685c0d71
DH
445 SCM_OUT_OF_RANGE (2, k);
446 else
447 SCM_WRONG_TYPE_ARG (1, list);
0f2d19dd 448}
1bbd0b84 449#undef FUNC_NAME
0f2d19dd 450
685c0d71 451
3b3b36dd 452SCM_DEFINE (scm_list_set_x, "list-set!", 3, 0, 0,
685c0d71
DH
453 (SCM list, SCM k, SCM val),
454 "Set the @var{k}th element of @var{list} to @var{val}.")
1bbd0b84
GB
455#define FUNC_NAME s_scm_list_set_x
456{
685c0d71 457 SCM lst = list;
a55c2b68 458 unsigned long int i = scm_to_ulong (k);
d2e53ed6 459 while (scm_is_pair (lst)) {
685c0d71
DH
460 if (i == 0) {
461 SCM_SETCAR (lst, val);
462 return val;
463 } else {
464 --i;
465 lst = SCM_CDR (lst);
466 }
467 };
c96d76b8 468 if (SCM_NULL_OR_NIL_P (lst))
685c0d71
DH
469 SCM_OUT_OF_RANGE (2, k);
470 else
471 SCM_WRONG_TYPE_ARG (1, list);
0f2d19dd 472}
1bbd0b84 473#undef FUNC_NAME
0f2d19dd
JB
474
475
1bbd0b84
GB
476SCM_REGISTER_PROC(s_list_cdr_ref, "list-cdr-ref", 2, 0, 0, scm_list_tail);
477
3b3b36dd 478SCM_DEFINE (scm_list_tail, "list-tail", 2, 0, 0,
1bbd0b84 479 (SCM lst, SCM k),
8f85c0c6 480 "@deffnx {Scheme Procedure} list-cdr-ref lst k\n"
b380b885
MD
481 "Return the \"tail\" of @var{lst} beginning with its @var{k}th element.\n"
482 "The first element of the list is considered to be element 0.\n\n"
872e0c72 483 "@code{list-tail} and @code{list-cdr-ref} are identical. It may help to\n"
b380b885
MD
484 "think of @code{list-cdr-ref} as accessing the @var{k}th cdr of the list,\n"
485 "or returning the results of cdring @var{k} times down @var{lst}.")
1bbd0b84 486#define FUNC_NAME s_scm_list_tail
df13742c 487{
a55c2b68 488 size_t i = scm_to_size_t (k);
df13742c 489 while (i-- > 0) {
34d19ef6 490 SCM_VALIDATE_CONS (1, lst);
df13742c
JB
491 lst = SCM_CDR(lst);
492 }
493 return lst;
494}
1bbd0b84 495#undef FUNC_NAME
df13742c 496
0f2d19dd 497
3b3b36dd 498SCM_DEFINE (scm_list_cdr_set_x, "list-cdr-set!", 3, 0, 0,
685c0d71
DH
499 (SCM list, SCM k, SCM val),
500 "Set the @var{k}th cdr of @var{list} to @var{val}.")
1bbd0b84
GB
501#define FUNC_NAME s_scm_list_cdr_set_x
502{
685c0d71 503 SCM lst = list;
a55c2b68 504 size_t i = scm_to_size_t (k);
d2e53ed6 505 while (scm_is_pair (lst)) {
685c0d71
DH
506 if (i == 0) {
507 SCM_SETCDR (lst, val);
508 return val;
509 } else {
510 --i;
511 lst = SCM_CDR (lst);
512 }
513 };
c96d76b8 514 if (SCM_NULL_OR_NIL_P (lst))
685c0d71
DH
515 SCM_OUT_OF_RANGE (2, k);
516 else
517 SCM_WRONG_TYPE_ARG (1, list);
0f2d19dd 518}
1bbd0b84 519#undef FUNC_NAME
0f2d19dd
JB
520
521
522\f
df13742c 523/* copying lists, perhaps partially */
0f2d19dd 524
3b3b36dd 525SCM_DEFINE (scm_list_head, "list-head", 2, 0, 0,
1bbd0b84 526 (SCM lst, SCM k),
b380b885
MD
527 "Copy the first @var{k} elements from @var{lst} into a new list, and\n"
528 "return it.")
1bbd0b84 529#define FUNC_NAME s_scm_list_head
0f2d19dd
JB
530{
531 SCM answer;
532 SCM * pos;
a55c2b68 533 size_t i = scm_to_size_t (k);
0f2d19dd 534
0f2d19dd
JB
535 answer = SCM_EOL;
536 pos = &answer;
0f2d19dd
JB
537 while (i-- > 0)
538 {
34d19ef6 539 SCM_VALIDATE_CONS (1, lst);
0f2d19dd 540 *pos = scm_cons (SCM_CAR (lst), SCM_EOL);
25d8012c 541 pos = SCM_CDRLOC (*pos);
0f2d19dd
JB
542 lst = SCM_CDR(lst);
543 }
544 return answer;
545}
1bbd0b84 546#undef FUNC_NAME
0f2d19dd
JB
547
548
212e58ed
DH
549/* Copy a list which is known to be finite. The last pair may or may not have
550 * a '() in its cdr. That is, improper lists are accepted. */
551SCM
552scm_i_finite_list_copy (SCM list)
553{
d2e53ed6 554 if (!scm_is_pair (list))
212e58ed
DH
555 {
556 return list;
557 }
558 else
559 {
560 SCM tail;
561 const SCM result = tail = scm_list_1 (SCM_CAR (list));
562 list = SCM_CDR (list);
d2e53ed6 563 while (scm_is_pair (list))
212e58ed
DH
564 {
565 const SCM new_tail = scm_list_1 (SCM_CAR (list));
566 SCM_SETCDR (tail, new_tail);
567 tail = new_tail;
568 list = SCM_CDR (list);
569 }
570 SCM_SETCDR (tail, list);
571
572 return result;
573 }
574}
575
576
a1ec6916 577SCM_DEFINE (scm_list_copy, "list-copy", 1, 0, 0,
1bbd0b84 578 (SCM lst),
b380b885 579 "Return a (newly-created) copy of @var{lst}.")
1bbd0b84 580#define FUNC_NAME s_scm_list_copy
df13742c
JB
581{
582 SCM newlst;
583 SCM * fill_here;
584 SCM from_here;
585
5d6bb349
KN
586 SCM_VALIDATE_LIST (1, lst);
587
df13742c
JB
588 newlst = SCM_EOL;
589 fill_here = &newlst;
590 from_here = lst;
591
d2e53ed6 592 while (scm_is_pair (from_here))
df13742c
JB
593 {
594 SCM c;
595 c = scm_cons (SCM_CAR (from_here), SCM_CDR (from_here));
596 *fill_here = c;
25d8012c 597 fill_here = SCM_CDRLOC (c);
df13742c
JB
598 from_here = SCM_CDR (from_here);
599 }
600 return newlst;
601}
1bbd0b84 602#undef FUNC_NAME
df13742c 603
fad3aaf1
KR
604
605SCM_PROC (s_list, "list", 0, 0, 1, scm_list_copy);
123a1b62 606SCM_SNARF_DOCS (primitive, scm_list_copy, "list", (SCM objs), 0, 0, 1,
fad3aaf1
KR
607 "Return a list containing @var{objs}, the arguments to\n"
608 "@code{list}.")
609
303bddc8
KR
610/* This used to be the code for "list", but it's wrong when used via apply
611 (it should copy the list). It seems pretty unlikely anyone would have
612 been using this from C code, since it's a no-op, but keep it for strict
613 binary compatibility. */
614SCM
615scm_list (SCM objs)
616{
617 return objs;
618}
619
fad3aaf1 620
0f2d19dd 621\f
df13742c
JB
622/* membership tests (memq, memv, etc.) */
623
79a3dafe
DH
624/* The function scm_c_memq returns the first sublist of list whose car is
625 * 'eq?' obj, where the sublists of list are the non-empty lists returned by
626 * (list-tail list k) for k less than the length of list. If obj does not
1e6808ea 627 * occur in list, then #f (not the empty list) is returned.
79a3dafe
DH
628 * List must be a proper list, otherwise scm_c_memq may crash or loop
629 * endlessly.
630 */
631SCM
632scm_c_memq (SCM obj, SCM list)
633{
c96d76b8 634 for (; !SCM_NULL_OR_NIL_P (list); list = SCM_CDR (list))
79a3dafe 635 {
bc36d050 636 if (scm_is_eq (SCM_CAR (list), obj))
79a3dafe
DH
637 return list;
638 }
639 return SCM_BOOL_F;
640}
641
642
3b3b36dd 643SCM_DEFINE (scm_memq, "memq", 2, 0, 0,
1bbd0b84 644 (SCM x, SCM lst),
5352393c
MG
645 "Return the first sublist of @var{lst} whose car is @code{eq?}\n"
646 "to @var{x} where the sublists of @var{lst} are the non-empty\n"
647 "lists returned by @code{(list-tail @var{lst} @var{k})} for\n"
648 "@var{k} less than the length of @var{lst}. If @var{x} does not\n"
649 "occur in @var{lst}, then @code{#f} (not the empty list) is\n"
650 "returned.")
1bbd0b84 651#define FUNC_NAME s_scm_memq
0f2d19dd 652{
3b7f4ba3
AW
653 SCM hare = lst, tortoise = lst;
654
655 while (scm_is_pair (hare))
656 {
657 if (scm_is_eq (SCM_CAR (hare), x))
658 return hare;
659 else
660 hare = SCM_CDR (hare);
661
662 if (!scm_is_pair (hare))
663 break;
664
665 if (scm_is_eq (SCM_CAR (hare), x))
666 return hare;
667 else
668 hare = SCM_CDR (hare);
669
670 tortoise = SCM_CDR (tortoise);
671 if (SCM_UNLIKELY (scm_is_eq (hare, tortoise)))
672 break;
673 }
674
675 if (SCM_LIKELY (scm_is_null (hare)))
676 return SCM_BOOL_F;
677 else
678 scm_wrong_type_arg_msg (FUNC_NAME, 2, lst, "list");
0f2d19dd 679}
1bbd0b84 680#undef FUNC_NAME
0f2d19dd
JB
681
682
3b3b36dd 683SCM_DEFINE (scm_memv, "memv", 2, 0, 0,
1bbd0b84 684 (SCM x, SCM lst),
5352393c
MG
685 "Return the first sublist of @var{lst} whose car is @code{eqv?}\n"
686 "to @var{x} where the sublists of @var{lst} are the non-empty\n"
687 "lists returned by @code{(list-tail @var{lst} @var{k})} for\n"
688 "@var{k} less than the length of @var{lst}. If @var{x} does not\n"
689 "occur in @var{lst}, then @code{#f} (not the empty list) is\n"
690 "returned.")
1bbd0b84 691#define FUNC_NAME s_scm_memv
0f2d19dd 692{
3b7f4ba3
AW
693 SCM hare = lst, tortoise = lst;
694
695 while (scm_is_pair (hare))
daa6ba18 696 {
3b7f4ba3
AW
697 if (scm_is_true (scm_eqv_p (SCM_CAR (hare), x)))
698 return hare;
699 else
700 hare = SCM_CDR (hare);
701
702 if (!scm_is_pair (hare))
703 break;
704
705 if (scm_is_true (scm_eqv_p (SCM_CAR (hare), x)))
706 return hare;
707 else
708 hare = SCM_CDR (hare);
709
710 tortoise = SCM_CDR (tortoise);
711 if (SCM_UNLIKELY (scm_is_eq (hare, tortoise)))
712 break;
daa6ba18 713 }
3b7f4ba3
AW
714
715 if (SCM_LIKELY (scm_is_null (hare)))
716 return SCM_BOOL_F;
717 else
718 scm_wrong_type_arg_msg (FUNC_NAME, 2, lst, "list");
0f2d19dd 719}
1bbd0b84 720#undef FUNC_NAME
0f2d19dd
JB
721
722
3b3b36dd 723SCM_DEFINE (scm_member, "member", 2, 0, 0,
1bbd0b84 724 (SCM x, SCM lst),
5352393c
MG
725 "Return the first sublist of @var{lst} whose car is\n"
726 "@code{equal?} to @var{x} where the sublists of @var{lst} are\n"
727 "the non-empty lists returned by @code{(list-tail @var{lst}\n"
728 "@var{k})} for @var{k} less than the length of @var{lst}. If\n"
729 "@var{x} does not occur in @var{lst}, then @code{#f} (not the\n"
730 "empty list) is returned.")
1bbd0b84 731#define FUNC_NAME s_scm_member
0f2d19dd 732{
daa6ba18 733 SCM_VALIDATE_LIST (2, lst);
c96d76b8 734 for (; !SCM_NULL_OR_NIL_P (lst); lst = SCM_CDR (lst))
daa6ba18 735 {
7888309b 736 if (! scm_is_false (scm_equal_p (SCM_CAR (lst), x)))
daa6ba18
DH
737 return lst;
738 }
739 return SCM_BOOL_F;
0f2d19dd 740}
1bbd0b84 741#undef FUNC_NAME
0f2d19dd 742
0f2d19dd 743\f
df13742c 744/* deleting elements from a list (delq, etc.) */
0f2d19dd 745
3b3b36dd 746SCM_DEFINE (scm_delq_x, "delq!", 2, 0, 0,
1bbd0b84 747 (SCM item, SCM lst),
8f85c0c6
NJ
748 "@deffnx {Scheme Procedure} delv! item lst\n"
749 "@deffnx {Scheme Procedure} delete! item lst\n"
b380b885 750 "These procedures are destructive versions of @code{delq}, @code{delv}\n"
bfefbf18 751 "and @code{delete}: they modify the existing @var{lst}\n"
b380b885
MD
752 "rather than creating a new list. Caveat evaluator: Like other\n"
753 "destructive list functions, these functions cannot modify the binding of\n"
754 "@var{lst}, and so cannot be used to delete the first element of\n"
755 "@var{lst} destructively.")
1bbd0b84 756#define FUNC_NAME s_scm_delq_x
0f2d19dd 757{
164271a1
JB
758 SCM walk;
759 SCM *prev;
0f2d19dd 760
164271a1 761 for (prev = &lst, walk = lst;
d2e53ed6 762 scm_is_pair (walk);
164271a1 763 walk = SCM_CDR (walk))
0f2d19dd 764 {
bc36d050 765 if (scm_is_eq (SCM_CAR (walk), item))
164271a1
JB
766 *prev = SCM_CDR (walk);
767 else
768 prev = SCM_CDRLOC (walk);
0f2d19dd 769 }
164271a1
JB
770
771 return lst;
0f2d19dd 772}
1bbd0b84 773#undef FUNC_NAME
0f2d19dd
JB
774
775
3b3b36dd 776SCM_DEFINE (scm_delv_x, "delv!", 2, 0, 0,
5352393c
MG
777 (SCM item, SCM lst),
778 "Destructively remove all elements from @var{lst} that are\n"
779 "@code{eqv?} to @var{item}.")
1bbd0b84 780#define FUNC_NAME s_scm_delv_x
0f2d19dd 781{
164271a1
JB
782 SCM walk;
783 SCM *prev;
0f2d19dd 784
164271a1 785 for (prev = &lst, walk = lst;
d2e53ed6 786 scm_is_pair (walk);
164271a1 787 walk = SCM_CDR (walk))
0f2d19dd 788 {
7888309b 789 if (! scm_is_false (scm_eqv_p (SCM_CAR (walk), item)))
164271a1
JB
790 *prev = SCM_CDR (walk);
791 else
792 prev = SCM_CDRLOC (walk);
0f2d19dd 793 }
164271a1
JB
794
795 return lst;
0f2d19dd 796}
1bbd0b84 797#undef FUNC_NAME
0f2d19dd
JB
798
799
800
3b3b36dd 801SCM_DEFINE (scm_delete_x, "delete!", 2, 0, 0,
5352393c
MG
802 (SCM item, SCM lst),
803 "Destructively remove all elements from @var{lst} that are\n"
804 "@code{equal?} to @var{item}.")
1bbd0b84 805#define FUNC_NAME s_scm_delete_x
0f2d19dd 806{
164271a1
JB
807 SCM walk;
808 SCM *prev;
0f2d19dd 809
164271a1 810 for (prev = &lst, walk = lst;
d2e53ed6 811 scm_is_pair (walk);
164271a1 812 walk = SCM_CDR (walk))
0f2d19dd 813 {
7888309b 814 if (! scm_is_false (scm_equal_p (SCM_CAR (walk), item)))
164271a1
JB
815 *prev = SCM_CDR (walk);
816 else
817 prev = SCM_CDRLOC (walk);
0f2d19dd 818 }
164271a1
JB
819
820 return lst;
0f2d19dd 821}
1bbd0b84 822#undef FUNC_NAME
0f2d19dd
JB
823
824
825\f
826
0f2d19dd 827
a1ec6916 828SCM_DEFINE (scm_delq, "delq", 2, 0, 0,
1bbd0b84 829 (SCM item, SCM lst),
5352393c
MG
830 "Return a newly-created copy of @var{lst} with elements\n"
831 "@code{eq?} to @var{item} removed. This procedure mirrors\n"
832 "@code{memq}: @code{delq} compares elements of @var{lst} against\n"
833 "@var{item} with @code{eq?}.")
1bbd0b84 834#define FUNC_NAME s_scm_delq
0f2d19dd 835{
1bbd0b84 836 SCM copy = scm_list_copy (lst);
0f2d19dd
JB
837 return scm_delq_x (item, copy);
838}
1bbd0b84 839#undef FUNC_NAME
0f2d19dd 840
a1ec6916 841SCM_DEFINE (scm_delv, "delv", 2, 0, 0,
1bbd0b84 842 (SCM item, SCM lst),
5352393c
MG
843 "Return a newly-created copy of @var{lst} with elements\n"
844 "@code{eqv?} to @var{item} removed. This procedure mirrors\n"
845 "@code{memv}: @code{delv} compares elements of @var{lst} against\n"
846 "@var{item} with @code{eqv?}.")
1bbd0b84 847#define FUNC_NAME s_scm_delv
0f2d19dd 848{
1bbd0b84 849 SCM copy = scm_list_copy (lst);
0f2d19dd
JB
850 return scm_delv_x (item, copy);
851}
1bbd0b84 852#undef FUNC_NAME
0f2d19dd 853
a1ec6916 854SCM_DEFINE (scm_delete, "delete", 2, 0, 0,
1bbd0b84 855 (SCM item, SCM lst),
5352393c
MG
856 "Return a newly-created copy of @var{lst} with elements\n"
857 "@code{equal?} to @var{item} removed. This procedure mirrors\n"
858 "@code{member}: @code{delete} compares elements of @var{lst}\n"
859 "against @var{item} with @code{equal?}.")
1bbd0b84 860#define FUNC_NAME s_scm_delete
0f2d19dd 861{
1bbd0b84 862 SCM copy = scm_list_copy (lst);
0f2d19dd
JB
863 return scm_delete_x (item, copy);
864}
1bbd0b84 865#undef FUNC_NAME
0f2d19dd
JB
866
867
3b3b36dd 868SCM_DEFINE (scm_delq1_x, "delq1!", 2, 0, 0,
1bbd0b84 869 (SCM item, SCM lst),
5352393c
MG
870 "Like @code{delq!}, but only deletes the first occurrence of\n"
871 "@var{item} from @var{lst}. Tests for equality using\n"
872 "@code{eq?}. See also @code{delv1!} and @code{delete1!}.")
1bbd0b84 873#define FUNC_NAME s_scm_delq1_x
82dc9f57
MD
874{
875 SCM walk;
876 SCM *prev;
877
878 for (prev = &lst, walk = lst;
d2e53ed6 879 scm_is_pair (walk);
82dc9f57
MD
880 walk = SCM_CDR (walk))
881 {
bc36d050 882 if (scm_is_eq (SCM_CAR (walk), item))
82dc9f57
MD
883 {
884 *prev = SCM_CDR (walk);
885 break;
886 }
887 else
888 prev = SCM_CDRLOC (walk);
889 }
890
891 return lst;
892}
1bbd0b84 893#undef FUNC_NAME
82dc9f57
MD
894
895
3b3b36dd 896SCM_DEFINE (scm_delv1_x, "delv1!", 2, 0, 0,
8507b88c 897 (SCM item, SCM lst),
5352393c
MG
898 "Like @code{delv!}, but only deletes the first occurrence of\n"
899 "@var{item} from @var{lst}. Tests for equality using\n"
900 "@code{eqv?}. See also @code{delq1!} and @code{delete1!}.")
1bbd0b84 901#define FUNC_NAME s_scm_delv1_x
82dc9f57
MD
902{
903 SCM walk;
904 SCM *prev;
905
906 for (prev = &lst, walk = lst;
d2e53ed6 907 scm_is_pair (walk);
82dc9f57
MD
908 walk = SCM_CDR (walk))
909 {
7888309b 910 if (! scm_is_false (scm_eqv_p (SCM_CAR (walk), item)))
82dc9f57
MD
911 {
912 *prev = SCM_CDR (walk);
913 break;
914 }
915 else
916 prev = SCM_CDRLOC (walk);
917 }
918
919 return lst;
920}
1bbd0b84 921#undef FUNC_NAME
82dc9f57
MD
922
923
3b3b36dd 924SCM_DEFINE (scm_delete1_x, "delete1!", 2, 0, 0,
8507b88c 925 (SCM item, SCM lst),
5352393c
MG
926 "Like @code{delete!}, but only deletes the first occurrence of\n"
927 "@var{item} from @var{lst}. Tests for equality using\n"
928 "@code{equal?}. See also @code{delq1!} and @code{delv1!}.")
1bbd0b84 929#define FUNC_NAME s_scm_delete1_x
82dc9f57
MD
930{
931 SCM walk;
932 SCM *prev;
933
934 for (prev = &lst, walk = lst;
d2e53ed6 935 scm_is_pair (walk);
82dc9f57
MD
936 walk = SCM_CDR (walk))
937 {
7888309b 938 if (! scm_is_false (scm_equal_p (SCM_CAR (walk), item)))
82dc9f57
MD
939 {
940 *prev = SCM_CDR (walk);
941 break;
942 }
943 else
944 prev = SCM_CDRLOC (walk);
945 }
946
947 return lst;
948}
1bbd0b84 949#undef FUNC_NAME
82dc9f57 950
c614a00b
MD
951SCM_DEFINE (scm_filter, "filter", 2, 0, 0,
952 (SCM pred, SCM list),
953 "Return all the elements of 2nd arg @var{list} that satisfy predicate @var{pred}.\n"
954 "The list is not disordered -- elements that appear in the result list occur\n"
955 "in the same order as they occur in the argument list. The returned list may\n"
956 "share a common tail with the argument list. The dynamic order in which the\n"
957 "various applications of pred are made is not specified.\n\n"
958 "@lisp\n"
959 "(filter even? '(0 7 8 8 43 -4)) => (0 8 8 -4)\n"
960 "@end lisp")
961#define FUNC_NAME s_scm_filter
962{
c614a00b
MD
963 SCM walk;
964 SCM *prev;
965 SCM res = SCM_EOL;
6c9e8a53 966 SCM_ASSERT (scm_is_true (scm_procedure_p (pred)), pred, 1, FUNC_NAME);
c614a00b
MD
967 SCM_VALIDATE_LIST (2, list);
968
969 for (prev = &res, walk = list;
d2e53ed6 970 scm_is_pair (walk);
c614a00b
MD
971 walk = SCM_CDR (walk))
972 {
6c9e8a53 973 if (scm_is_true (scm_call_1 (pred, SCM_CAR (walk))))
c614a00b
MD
974 {
975 *prev = scm_cons (SCM_CAR (walk), SCM_EOL);
976 prev = SCM_CDRLOC (*prev);
977 }
978 }
979
980 return res;
981}
982#undef FUNC_NAME
983
984SCM_DEFINE (scm_filter_x, "filter!", 2, 0, 0,
985 (SCM pred, SCM list),
986 "Linear-update variant of @code{filter}.")
987#define FUNC_NAME s_scm_filter_x
988{
c614a00b
MD
989 SCM walk;
990 SCM *prev;
6c9e8a53 991 SCM_ASSERT (scm_is_true (scm_procedure_p (pred)), pred, 1, FUNC_NAME);
c614a00b
MD
992 SCM_VALIDATE_LIST (2, list);
993
994 for (prev = &list, walk = list;
d2e53ed6 995 scm_is_pair (walk);
c614a00b
MD
996 walk = SCM_CDR (walk))
997 {
6c9e8a53 998 if (scm_is_true (scm_call_1 (pred, SCM_CAR (walk))))
c614a00b
MD
999 prev = SCM_CDRLOC (walk);
1000 else
1001 *prev = SCM_CDR (walk);
1002 }
1003
1004 return list;
1005}
1006#undef FUNC_NAME
82dc9f57 1007
0f2d19dd 1008\f
0f2d19dd
JB
1009void
1010scm_init_list ()
0f2d19dd 1011{
a0599745 1012#include "libguile/list.x"
0f2d19dd 1013}
89e00824
ML
1014
1015/*
1016 Local Variables:
1017 c-file-style: "gnu"
1018 End:
1019*/