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