Update Gnulib to v0.0-6827-g39c3009; use the `dirfd' module.
[bpt/guile.git] / libguile / list.c
CommitLineData
3b7f4ba3 1/* Copyright (C) 1995,1996,1997,2000,2001,2003,2004,2008,2009,2010,2011
212e58ed 2 * 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)
eb741d98
HWN
93 if (SCM_NIMP (elt))
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
ML
181long
182scm_ilength(SCM sx)
0f2d19dd 183{
c014a02e 184 long i = 0;
e1385ffc
GB
185 SCM tortoise = sx;
186 SCM hare = sx;
df13742c 187
0f2d19dd 188 do {
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++;
c96d76b8 193 if (SCM_NULL_OR_NIL_P(hare)) return i;
d2e53ed6 194 if (!scm_is_pair (hare)) return -1;
df13742c 195 hare = SCM_CDR(hare);
0f2d19dd 196 i++;
448a3bc2
JB
197 /* For every two steps the hare takes, the tortoise takes one. */
198 tortoise = SCM_CDR(tortoise);
0f2d19dd 199 }
bc36d050 200 while (!scm_is_eq (hare, tortoise));
df13742c 201
448a3bc2 202 /* If the tortoise ever catches the hare, then the list must contain
df13742c 203 a cycle. */
0f2d19dd
JB
204 return -1;
205}
206
2de14ecd 207
3b3b36dd 208SCM_DEFINE (scm_length, "length", 1, 0, 0,
1bbd0b84 209 (SCM lst),
5352393c 210 "Return the number of elements in list @var{lst}.")
1bbd0b84 211#define FUNC_NAME s_scm_length
0f2d19dd 212{
c014a02e 213 long i;
34d19ef6 214 SCM_VALIDATE_LIST_COPYLEN (1, lst, i);
e11e83f3 215 return scm_from_long (i);
0f2d19dd 216}
1bbd0b84 217#undef FUNC_NAME
0f2d19dd
JB
218
219
220\f
df13742c 221/* appending lists */
0f2d19dd 222
a1ec6916 223SCM_DEFINE (scm_append, "append", 0, 0, 1,
1bbd0b84 224 (SCM args),
5352393c
MG
225 "Return a list consisting of the elements the lists passed as\n"
226 "arguments.\n"
1e6808ea 227 "@lisp\n"
5352393c
MG
228 "(append '(x) '(y)) @result{} (x y)\n"
229 "(append '(a) '(b c d)) @result{} (a b c d)\n"
230 "(append '(a (b)) '((c))) @result{} (a (b) (c))\n"
1e6808ea 231 "@end lisp\n"
5352393c
MG
232 "The resulting list is always newly allocated, except that it\n"
233 "shares structure with the last list argument. The last\n"
234 "argument may actually be any object; an improper list results\n"
235 "if the last argument is not a proper list.\n"
1e6808ea 236 "@lisp\n"
5352393c
MG
237 "(append '(a b) '(c . d)) @result{} (a b c . d)\n"
238 "(append '() 'a) @result{} a\n"
1e6808ea 239 "@end lisp")
1bbd0b84 240#define FUNC_NAME s_scm_append
0f2d19dd 241{
af45e3b0 242 SCM_VALIDATE_REST_ARGUMENT (args);
d2e53ed6 243 if (scm_is_null (args)) {
af45e3b0
DH
244 return SCM_EOL;
245 } else {
246 SCM res = SCM_EOL;
247 SCM *lloc = &res;
248 SCM arg = SCM_CAR (args);
4c13270f 249 int argnum = 1;
af45e3b0 250 args = SCM_CDR (args);
d2e53ed6
MV
251 while (!scm_is_null (args)) {
252 while (scm_is_pair (arg)) {
af45e3b0
DH
253 *lloc = scm_cons (SCM_CAR (arg), SCM_EOL);
254 lloc = SCM_CDRLOC (*lloc);
255 arg = SCM_CDR (arg);
256 }
4c13270f 257 SCM_VALIDATE_NULL_OR_NIL (argnum, arg);
af45e3b0
DH
258 arg = SCM_CAR (args);
259 args = SCM_CDR (args);
4c13270f 260 argnum++;
af45e3b0
DH
261 };
262 *lloc = arg;
0f2d19dd
JB
263 return res;
264 }
0f2d19dd 265}
1bbd0b84 266#undef FUNC_NAME
0f2d19dd
JB
267
268
a1ec6916 269SCM_DEFINE (scm_append_x, "append!", 0, 0, 1,
1e6808ea
MG
270 (SCM lists),
271 "A destructive version of @code{append} (@pxref{Pairs and\n"
7a095584 272 "Lists,,,r5rs, The Revised^5 Report on Scheme}). The cdr field\n"
1e6808ea 273 "of each list's final pair is changed to point to the head of\n"
71a89639 274 "the next list, so no consing is performed. Return\n"
1e6808ea 275 "the mutated list.")
1bbd0b84 276#define FUNC_NAME s_scm_append_x
0f2d19dd 277{
d4641098 278 SCM ret, *loc;
1e6808ea 279 SCM_VALIDATE_REST_ARGUMENT (lists);
d4641098 280
d2e53ed6 281 if (scm_is_null (lists))
d4641098
KR
282 return SCM_EOL;
283
284 loc = &ret;
285 for (;;)
286 {
1e6808ea 287 SCM arg = SCM_CAR (lists);
d4641098
KR
288 *loc = arg;
289
1e6808ea 290 lists = SCM_CDR (lists);
d2e53ed6 291 if (scm_is_null (lists))
d4641098
KR
292 return ret;
293
294 if (!SCM_NULL_OR_NIL_P (arg))
295 {
296 SCM_VALIDATE_CONS (SCM_ARG1, arg);
297 loc = SCM_CDRLOC (scm_last_pair (arg));
298 }
af45e3b0 299 }
0f2d19dd 300}
1bbd0b84 301#undef FUNC_NAME
0f2d19dd
JB
302
303
3b3b36dd 304SCM_DEFINE (scm_last_pair, "last-pair", 1, 0, 0,
e1385ffc 305 (SCM lst),
71a89639 306 "Return the last pair in @var{lst}, signalling an error if\n"
b380b885 307 "@var{lst} is circular.")
1bbd0b84 308#define FUNC_NAME s_scm_last_pair
df13742c 309{
e1385ffc
GB
310 SCM tortoise = lst;
311 SCM hare = lst;
0f2d19dd 312
c96d76b8
NJ
313 if (SCM_NULL_OR_NIL_P (lst))
314 return lst;
df13742c 315
e1385ffc
GB
316 SCM_VALIDATE_CONS (SCM_ARG1, lst);
317 do {
318 SCM ahead = SCM_CDR(hare);
d2e53ed6 319 if (!scm_is_pair (ahead)) return hare;
e1385ffc
GB
320 hare = ahead;
321 ahead = SCM_CDR(hare);
d2e53ed6 322 if (!scm_is_pair (ahead)) return hare;
e1385ffc
GB
323 hare = ahead;
324 tortoise = SCM_CDR(tortoise);
df13742c 325 }
bc36d050 326 while (!scm_is_eq (hare, tortoise));
1afff620 327 SCM_MISC_ERROR ("Circular structure in position 1: ~S", scm_list_1 (lst));
df13742c 328}
1bbd0b84 329#undef FUNC_NAME
df13742c
JB
330
331\f
332/* reversing lists */
0f2d19dd 333
a1ec6916 334SCM_DEFINE (scm_reverse, "reverse", 1, 0, 0,
e1385ffc 335 (SCM lst),
5352393c
MG
336 "Return a new list that contains the elements of @var{lst} but\n"
337 "in reverse order.")
e1385ffc
GB
338#define FUNC_NAME s_scm_reverse
339{
340 SCM result = SCM_EOL;
341 SCM tortoise = lst;
342 SCM hare = lst;
343
344 do {
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);
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);
353 tortoise = SCM_CDR (tortoise);
354 }
bc36d050 355 while (!scm_is_eq (hare, tortoise));
1afff620 356 SCM_MISC_ERROR ("Circular structure in position 1: ~S", scm_list_1 (lst));
e1385ffc
GB
357}
358#undef FUNC_NAME
359
360SCM_DEFINE (scm_reverse_x, "reverse!", 1, 1, 0,
361 (SCM lst, SCM new_tail),
7a095584
NJ
362 "A destructive version of @code{reverse} (@pxref{Pairs and Lists,,,r5rs,\n"
363 "The Revised^5 Report on Scheme}). The cdr of each cell in @var{lst} is\n"
71a89639
MV
364 "modified to point to the previous list element. Return the\n"
365 "reversed list.\n\n"
b380b885
MD
366 "Caveat: because the list is modified in place, the tail of the original\n"
367 "list now becomes its head, and the head of the original list now becomes\n"
368 "the tail. Therefore, the @var{lst} symbol to which the head of the\n"
369 "original list was bound now points to the tail. To ensure that the head\n"
370 "of the modified list is not lost, it is wise to save the return value of\n"
371 "@code{reverse!}")
1bbd0b84 372#define FUNC_NAME s_scm_reverse_x
0f2d19dd 373{
e39c3de4 374 SCM_VALIDATE_LIST (1, lst);
3946f0de
MD
375 if (SCM_UNBNDP (new_tail))
376 new_tail = SCM_EOL;
377 else
e39c3de4 378 SCM_VALIDATE_LIST (2, new_tail);
0f2d19dd 379
c96d76b8 380 while (!SCM_NULL_OR_NIL_P (lst))
3946f0de 381 {
e1385ffc
GB
382 SCM old_tail = SCM_CDR (lst);
383 SCM_SETCDR (lst, new_tail);
384 new_tail = lst;
385 lst = old_tail;
3946f0de
MD
386 }
387 return new_tail;
0f2d19dd 388}
1bbd0b84 389#undef FUNC_NAME
0f2d19dd 390
0f2d19dd 391\f
685c0d71 392
df13742c 393/* indexing lists by element number */
0f2d19dd 394
3b3b36dd 395SCM_DEFINE (scm_list_ref, "list-ref", 2, 0, 0,
685c0d71 396 (SCM list, SCM k),
5352393c 397 "Return the @var{k}th element from @var{list}.")
1bbd0b84
GB
398#define FUNC_NAME s_scm_list_ref
399{
685c0d71 400 SCM lst = list;
c014a02e 401 unsigned long int i;
a55c2b68 402 i = scm_to_ulong (k);
d2e53ed6 403 while (scm_is_pair (lst)) {
685c0d71
DH
404 if (i == 0)
405 return SCM_CAR (lst);
406 else {
407 --i;
408 lst = SCM_CDR (lst);
409 }
410 };
c96d76b8 411 if (SCM_NULL_OR_NIL_P (lst))
685c0d71
DH
412 SCM_OUT_OF_RANGE (2, k);
413 else
414 SCM_WRONG_TYPE_ARG (1, list);
0f2d19dd 415}
1bbd0b84 416#undef FUNC_NAME
0f2d19dd 417
685c0d71 418
3b3b36dd 419SCM_DEFINE (scm_list_set_x, "list-set!", 3, 0, 0,
685c0d71
DH
420 (SCM list, SCM k, SCM val),
421 "Set the @var{k}th element of @var{list} to @var{val}.")
1bbd0b84
GB
422#define FUNC_NAME s_scm_list_set_x
423{
685c0d71 424 SCM lst = list;
a55c2b68 425 unsigned long int i = scm_to_ulong (k);
d2e53ed6 426 while (scm_is_pair (lst)) {
685c0d71
DH
427 if (i == 0) {
428 SCM_SETCAR (lst, val);
429 return val;
430 } else {
431 --i;
432 lst = SCM_CDR (lst);
433 }
434 };
c96d76b8 435 if (SCM_NULL_OR_NIL_P (lst))
685c0d71
DH
436 SCM_OUT_OF_RANGE (2, k);
437 else
438 SCM_WRONG_TYPE_ARG (1, list);
0f2d19dd 439}
1bbd0b84 440#undef FUNC_NAME
0f2d19dd
JB
441
442
1bbd0b84
GB
443SCM_REGISTER_PROC(s_list_cdr_ref, "list-cdr-ref", 2, 0, 0, scm_list_tail);
444
3b3b36dd 445SCM_DEFINE (scm_list_tail, "list-tail", 2, 0, 0,
1bbd0b84 446 (SCM lst, SCM k),
8f85c0c6 447 "@deffnx {Scheme Procedure} list-cdr-ref lst k\n"
b380b885
MD
448 "Return the \"tail\" of @var{lst} beginning with its @var{k}th element.\n"
449 "The first element of the list is considered to be element 0.\n\n"
872e0c72 450 "@code{list-tail} and @code{list-cdr-ref} are identical. It may help to\n"
b380b885
MD
451 "think of @code{list-cdr-ref} as accessing the @var{k}th cdr of the list,\n"
452 "or returning the results of cdring @var{k} times down @var{lst}.")
1bbd0b84 453#define FUNC_NAME s_scm_list_tail
df13742c 454{
a55c2b68 455 size_t i = scm_to_size_t (k);
df13742c 456 while (i-- > 0) {
34d19ef6 457 SCM_VALIDATE_CONS (1, lst);
df13742c
JB
458 lst = SCM_CDR(lst);
459 }
460 return lst;
461}
1bbd0b84 462#undef FUNC_NAME
df13742c 463
0f2d19dd 464
3b3b36dd 465SCM_DEFINE (scm_list_cdr_set_x, "list-cdr-set!", 3, 0, 0,
685c0d71
DH
466 (SCM list, SCM k, SCM val),
467 "Set the @var{k}th cdr of @var{list} to @var{val}.")
1bbd0b84
GB
468#define FUNC_NAME s_scm_list_cdr_set_x
469{
685c0d71 470 SCM lst = list;
a55c2b68 471 size_t i = scm_to_size_t (k);
d2e53ed6 472 while (scm_is_pair (lst)) {
685c0d71
DH
473 if (i == 0) {
474 SCM_SETCDR (lst, val);
475 return val;
476 } else {
477 --i;
478 lst = SCM_CDR (lst);
479 }
480 };
c96d76b8 481 if (SCM_NULL_OR_NIL_P (lst))
685c0d71
DH
482 SCM_OUT_OF_RANGE (2, k);
483 else
484 SCM_WRONG_TYPE_ARG (1, list);
0f2d19dd 485}
1bbd0b84 486#undef FUNC_NAME
0f2d19dd
JB
487
488
489\f
df13742c 490/* copying lists, perhaps partially */
0f2d19dd 491
3b3b36dd 492SCM_DEFINE (scm_list_head, "list-head", 2, 0, 0,
1bbd0b84 493 (SCM lst, SCM k),
b380b885
MD
494 "Copy the first @var{k} elements from @var{lst} into a new list, and\n"
495 "return it.")
1bbd0b84 496#define FUNC_NAME s_scm_list_head
0f2d19dd
JB
497{
498 SCM answer;
499 SCM * pos;
a55c2b68 500 size_t i = scm_to_size_t (k);
0f2d19dd 501
0f2d19dd
JB
502 answer = SCM_EOL;
503 pos = &answer;
0f2d19dd
JB
504 while (i-- > 0)
505 {
34d19ef6 506 SCM_VALIDATE_CONS (1, lst);
0f2d19dd 507 *pos = scm_cons (SCM_CAR (lst), SCM_EOL);
25d8012c 508 pos = SCM_CDRLOC (*pos);
0f2d19dd
JB
509 lst = SCM_CDR(lst);
510 }
511 return answer;
512}
1bbd0b84 513#undef FUNC_NAME
0f2d19dd
JB
514
515
212e58ed
DH
516/* Copy a list which is known to be finite. The last pair may or may not have
517 * a '() in its cdr. That is, improper lists are accepted. */
518SCM
519scm_i_finite_list_copy (SCM list)
520{
d2e53ed6 521 if (!scm_is_pair (list))
212e58ed
DH
522 {
523 return list;
524 }
525 else
526 {
527 SCM tail;
528 const SCM result = tail = scm_list_1 (SCM_CAR (list));
529 list = SCM_CDR (list);
d2e53ed6 530 while (scm_is_pair (list))
212e58ed
DH
531 {
532 const SCM new_tail = scm_list_1 (SCM_CAR (list));
533 SCM_SETCDR (tail, new_tail);
534 tail = new_tail;
535 list = SCM_CDR (list);
536 }
537 SCM_SETCDR (tail, list);
538
539 return result;
540 }
541}
542
543
a1ec6916 544SCM_DEFINE (scm_list_copy, "list-copy", 1, 0, 0,
1bbd0b84 545 (SCM lst),
b380b885 546 "Return a (newly-created) copy of @var{lst}.")
1bbd0b84 547#define FUNC_NAME s_scm_list_copy
df13742c
JB
548{
549 SCM newlst;
550 SCM * fill_here;
551 SCM from_here;
552
5d6bb349
KN
553 SCM_VALIDATE_LIST (1, lst);
554
df13742c
JB
555 newlst = SCM_EOL;
556 fill_here = &newlst;
557 from_here = lst;
558
d2e53ed6 559 while (scm_is_pair (from_here))
df13742c
JB
560 {
561 SCM c;
562 c = scm_cons (SCM_CAR (from_here), SCM_CDR (from_here));
563 *fill_here = c;
25d8012c 564 fill_here = SCM_CDRLOC (c);
df13742c
JB
565 from_here = SCM_CDR (from_here);
566 }
567 return newlst;
568}
1bbd0b84 569#undef FUNC_NAME
df13742c 570
fad3aaf1
KR
571
572SCM_PROC (s_list, "list", 0, 0, 1, scm_list_copy);
123a1b62 573SCM_SNARF_DOCS (primitive, scm_list_copy, "list", (SCM objs), 0, 0, 1,
fad3aaf1
KR
574 "Return a list containing @var{objs}, the arguments to\n"
575 "@code{list}.")
576
303bddc8
KR
577/* This used to be the code for "list", but it's wrong when used via apply
578 (it should copy the list). It seems pretty unlikely anyone would have
579 been using this from C code, since it's a no-op, but keep it for strict
580 binary compatibility. */
581SCM
582scm_list (SCM objs)
583{
584 return objs;
585}
586
fad3aaf1 587
0f2d19dd 588\f
df13742c
JB
589/* membership tests (memq, memv, etc.) */
590
79a3dafe
DH
591/* The function scm_c_memq returns the first sublist of list whose car is
592 * 'eq?' obj, where the sublists of list are the non-empty lists returned by
593 * (list-tail list k) for k less than the length of list. If obj does not
1e6808ea 594 * occur in list, then #f (not the empty list) is returned.
79a3dafe
DH
595 * List must be a proper list, otherwise scm_c_memq may crash or loop
596 * endlessly.
597 */
598SCM
599scm_c_memq (SCM obj, SCM list)
600{
c96d76b8 601 for (; !SCM_NULL_OR_NIL_P (list); list = SCM_CDR (list))
79a3dafe 602 {
bc36d050 603 if (scm_is_eq (SCM_CAR (list), obj))
79a3dafe
DH
604 return list;
605 }
606 return SCM_BOOL_F;
607}
608
609
3b3b36dd 610SCM_DEFINE (scm_memq, "memq", 2, 0, 0,
1bbd0b84 611 (SCM x, SCM lst),
5352393c
MG
612 "Return the first sublist of @var{lst} whose car is @code{eq?}\n"
613 "to @var{x} where the sublists of @var{lst} are the non-empty\n"
614 "lists returned by @code{(list-tail @var{lst} @var{k})} for\n"
615 "@var{k} less than the length of @var{lst}. If @var{x} does not\n"
616 "occur in @var{lst}, then @code{#f} (not the empty list) is\n"
617 "returned.")
1bbd0b84 618#define FUNC_NAME s_scm_memq
0f2d19dd 619{
3b7f4ba3
AW
620 SCM hare = lst, tortoise = lst;
621
622 while (scm_is_pair (hare))
623 {
624 if (scm_is_eq (SCM_CAR (hare), x))
625 return hare;
626 else
627 hare = SCM_CDR (hare);
628
629 if (!scm_is_pair (hare))
630 break;
631
632 if (scm_is_eq (SCM_CAR (hare), x))
633 return hare;
634 else
635 hare = SCM_CDR (hare);
636
637 tortoise = SCM_CDR (tortoise);
638 if (SCM_UNLIKELY (scm_is_eq (hare, tortoise)))
639 break;
640 }
641
642 if (SCM_LIKELY (scm_is_null (hare)))
643 return SCM_BOOL_F;
644 else
645 scm_wrong_type_arg_msg (FUNC_NAME, 2, lst, "list");
0f2d19dd 646}
1bbd0b84 647#undef FUNC_NAME
0f2d19dd
JB
648
649
3b3b36dd 650SCM_DEFINE (scm_memv, "memv", 2, 0, 0,
1bbd0b84 651 (SCM x, SCM lst),
5352393c
MG
652 "Return the first sublist of @var{lst} whose car is @code{eqv?}\n"
653 "to @var{x} where the sublists of @var{lst} are the non-empty\n"
654 "lists returned by @code{(list-tail @var{lst} @var{k})} for\n"
655 "@var{k} less than the length of @var{lst}. If @var{x} does not\n"
656 "occur in @var{lst}, then @code{#f} (not the empty list) is\n"
657 "returned.")
1bbd0b84 658#define FUNC_NAME s_scm_memv
0f2d19dd 659{
3b7f4ba3
AW
660 SCM hare = lst, tortoise = lst;
661
662 while (scm_is_pair (hare))
daa6ba18 663 {
3b7f4ba3
AW
664 if (scm_is_true (scm_eqv_p (SCM_CAR (hare), x)))
665 return hare;
666 else
667 hare = SCM_CDR (hare);
668
669 if (!scm_is_pair (hare))
670 break;
671
672 if (scm_is_true (scm_eqv_p (SCM_CAR (hare), x)))
673 return hare;
674 else
675 hare = SCM_CDR (hare);
676
677 tortoise = SCM_CDR (tortoise);
678 if (SCM_UNLIKELY (scm_is_eq (hare, tortoise)))
679 break;
daa6ba18 680 }
3b7f4ba3
AW
681
682 if (SCM_LIKELY (scm_is_null (hare)))
683 return SCM_BOOL_F;
684 else
685 scm_wrong_type_arg_msg (FUNC_NAME, 2, lst, "list");
0f2d19dd 686}
1bbd0b84 687#undef FUNC_NAME
0f2d19dd
JB
688
689
3b3b36dd 690SCM_DEFINE (scm_member, "member", 2, 0, 0,
1bbd0b84 691 (SCM x, SCM lst),
5352393c
MG
692 "Return the first sublist of @var{lst} whose car is\n"
693 "@code{equal?} to @var{x} where the sublists of @var{lst} are\n"
694 "the non-empty lists returned by @code{(list-tail @var{lst}\n"
695 "@var{k})} for @var{k} less than the length of @var{lst}. If\n"
696 "@var{x} does not occur in @var{lst}, then @code{#f} (not the\n"
697 "empty list) is returned.")
1bbd0b84 698#define FUNC_NAME s_scm_member
0f2d19dd 699{
daa6ba18 700 SCM_VALIDATE_LIST (2, lst);
c96d76b8 701 for (; !SCM_NULL_OR_NIL_P (lst); lst = SCM_CDR (lst))
daa6ba18 702 {
7888309b 703 if (! scm_is_false (scm_equal_p (SCM_CAR (lst), x)))
daa6ba18
DH
704 return lst;
705 }
706 return SCM_BOOL_F;
0f2d19dd 707}
1bbd0b84 708#undef FUNC_NAME
0f2d19dd 709
0f2d19dd 710\f
df13742c 711/* deleting elements from a list (delq, etc.) */
0f2d19dd 712
3b3b36dd 713SCM_DEFINE (scm_delq_x, "delq!", 2, 0, 0,
1bbd0b84 714 (SCM item, SCM lst),
8f85c0c6
NJ
715 "@deffnx {Scheme Procedure} delv! item lst\n"
716 "@deffnx {Scheme Procedure} delete! item lst\n"
b380b885 717 "These procedures are destructive versions of @code{delq}, @code{delv}\n"
bfefbf18 718 "and @code{delete}: they modify the existing @var{lst}\n"
b380b885
MD
719 "rather than creating a new list. Caveat evaluator: Like other\n"
720 "destructive list functions, these functions cannot modify the binding of\n"
721 "@var{lst}, and so cannot be used to delete the first element of\n"
722 "@var{lst} destructively.")
1bbd0b84 723#define FUNC_NAME s_scm_delq_x
0f2d19dd 724{
164271a1
JB
725 SCM walk;
726 SCM *prev;
0f2d19dd 727
164271a1 728 for (prev = &lst, walk = lst;
d2e53ed6 729 scm_is_pair (walk);
164271a1 730 walk = SCM_CDR (walk))
0f2d19dd 731 {
bc36d050 732 if (scm_is_eq (SCM_CAR (walk), item))
164271a1
JB
733 *prev = SCM_CDR (walk);
734 else
735 prev = SCM_CDRLOC (walk);
0f2d19dd 736 }
164271a1
JB
737
738 return lst;
0f2d19dd 739}
1bbd0b84 740#undef FUNC_NAME
0f2d19dd
JB
741
742
3b3b36dd 743SCM_DEFINE (scm_delv_x, "delv!", 2, 0, 0,
5352393c
MG
744 (SCM item, SCM lst),
745 "Destructively remove all elements from @var{lst} that are\n"
746 "@code{eqv?} to @var{item}.")
1bbd0b84 747#define FUNC_NAME s_scm_delv_x
0f2d19dd 748{
164271a1
JB
749 SCM walk;
750 SCM *prev;
0f2d19dd 751
164271a1 752 for (prev = &lst, walk = lst;
d2e53ed6 753 scm_is_pair (walk);
164271a1 754 walk = SCM_CDR (walk))
0f2d19dd 755 {
7888309b 756 if (! scm_is_false (scm_eqv_p (SCM_CAR (walk), item)))
164271a1
JB
757 *prev = SCM_CDR (walk);
758 else
759 prev = SCM_CDRLOC (walk);
0f2d19dd 760 }
164271a1
JB
761
762 return lst;
0f2d19dd 763}
1bbd0b84 764#undef FUNC_NAME
0f2d19dd
JB
765
766
767
3b3b36dd 768SCM_DEFINE (scm_delete_x, "delete!", 2, 0, 0,
5352393c
MG
769 (SCM item, SCM lst),
770 "Destructively remove all elements from @var{lst} that are\n"
771 "@code{equal?} to @var{item}.")
1bbd0b84 772#define FUNC_NAME s_scm_delete_x
0f2d19dd 773{
164271a1
JB
774 SCM walk;
775 SCM *prev;
0f2d19dd 776
164271a1 777 for (prev = &lst, walk = lst;
d2e53ed6 778 scm_is_pair (walk);
164271a1 779 walk = SCM_CDR (walk))
0f2d19dd 780 {
7888309b 781 if (! scm_is_false (scm_equal_p (SCM_CAR (walk), item)))
164271a1
JB
782 *prev = SCM_CDR (walk);
783 else
784 prev = SCM_CDRLOC (walk);
0f2d19dd 785 }
164271a1
JB
786
787 return lst;
0f2d19dd 788}
1bbd0b84 789#undef FUNC_NAME
0f2d19dd
JB
790
791
792\f
793
0f2d19dd 794
a1ec6916 795SCM_DEFINE (scm_delq, "delq", 2, 0, 0,
1bbd0b84 796 (SCM item, SCM lst),
5352393c
MG
797 "Return a newly-created copy of @var{lst} with elements\n"
798 "@code{eq?} to @var{item} removed. This procedure mirrors\n"
799 "@code{memq}: @code{delq} compares elements of @var{lst} against\n"
800 "@var{item} with @code{eq?}.")
1bbd0b84 801#define FUNC_NAME s_scm_delq
0f2d19dd 802{
1bbd0b84 803 SCM copy = scm_list_copy (lst);
0f2d19dd
JB
804 return scm_delq_x (item, copy);
805}
1bbd0b84 806#undef FUNC_NAME
0f2d19dd 807
a1ec6916 808SCM_DEFINE (scm_delv, "delv", 2, 0, 0,
1bbd0b84 809 (SCM item, SCM lst),
5352393c
MG
810 "Return a newly-created copy of @var{lst} with elements\n"
811 "@code{eqv?} to @var{item} removed. This procedure mirrors\n"
812 "@code{memv}: @code{delv} compares elements of @var{lst} against\n"
813 "@var{item} with @code{eqv?}.")
1bbd0b84 814#define FUNC_NAME s_scm_delv
0f2d19dd 815{
1bbd0b84 816 SCM copy = scm_list_copy (lst);
0f2d19dd
JB
817 return scm_delv_x (item, copy);
818}
1bbd0b84 819#undef FUNC_NAME
0f2d19dd 820
a1ec6916 821SCM_DEFINE (scm_delete, "delete", 2, 0, 0,
1bbd0b84 822 (SCM item, SCM lst),
5352393c
MG
823 "Return a newly-created copy of @var{lst} with elements\n"
824 "@code{equal?} to @var{item} removed. This procedure mirrors\n"
825 "@code{member}: @code{delete} compares elements of @var{lst}\n"
826 "against @var{item} with @code{equal?}.")
1bbd0b84 827#define FUNC_NAME s_scm_delete
0f2d19dd 828{
1bbd0b84 829 SCM copy = scm_list_copy (lst);
0f2d19dd
JB
830 return scm_delete_x (item, copy);
831}
1bbd0b84 832#undef FUNC_NAME
0f2d19dd
JB
833
834
3b3b36dd 835SCM_DEFINE (scm_delq1_x, "delq1!", 2, 0, 0,
1bbd0b84 836 (SCM item, SCM lst),
5352393c
MG
837 "Like @code{delq!}, but only deletes the first occurrence of\n"
838 "@var{item} from @var{lst}. Tests for equality using\n"
839 "@code{eq?}. See also @code{delv1!} and @code{delete1!}.")
1bbd0b84 840#define FUNC_NAME s_scm_delq1_x
82dc9f57
MD
841{
842 SCM walk;
843 SCM *prev;
844
845 for (prev = &lst, walk = lst;
d2e53ed6 846 scm_is_pair (walk);
82dc9f57
MD
847 walk = SCM_CDR (walk))
848 {
bc36d050 849 if (scm_is_eq (SCM_CAR (walk), item))
82dc9f57
MD
850 {
851 *prev = SCM_CDR (walk);
852 break;
853 }
854 else
855 prev = SCM_CDRLOC (walk);
856 }
857
858 return lst;
859}
1bbd0b84 860#undef FUNC_NAME
82dc9f57
MD
861
862
3b3b36dd 863SCM_DEFINE (scm_delv1_x, "delv1!", 2, 0, 0,
8507b88c 864 (SCM item, SCM lst),
5352393c
MG
865 "Like @code{delv!}, but only deletes the first occurrence of\n"
866 "@var{item} from @var{lst}. Tests for equality using\n"
867 "@code{eqv?}. See also @code{delq1!} and @code{delete1!}.")
1bbd0b84 868#define FUNC_NAME s_scm_delv1_x
82dc9f57
MD
869{
870 SCM walk;
871 SCM *prev;
872
873 for (prev = &lst, walk = lst;
d2e53ed6 874 scm_is_pair (walk);
82dc9f57
MD
875 walk = SCM_CDR (walk))
876 {
7888309b 877 if (! scm_is_false (scm_eqv_p (SCM_CAR (walk), item)))
82dc9f57
MD
878 {
879 *prev = SCM_CDR (walk);
880 break;
881 }
882 else
883 prev = SCM_CDRLOC (walk);
884 }
885
886 return lst;
887}
1bbd0b84 888#undef FUNC_NAME
82dc9f57
MD
889
890
3b3b36dd 891SCM_DEFINE (scm_delete1_x, "delete1!", 2, 0, 0,
8507b88c 892 (SCM item, SCM lst),
5352393c
MG
893 "Like @code{delete!}, but only deletes the first occurrence of\n"
894 "@var{item} from @var{lst}. Tests for equality using\n"
895 "@code{equal?}. See also @code{delq1!} and @code{delv1!}.")
1bbd0b84 896#define FUNC_NAME s_scm_delete1_x
82dc9f57
MD
897{
898 SCM walk;
899 SCM *prev;
900
901 for (prev = &lst, walk = lst;
d2e53ed6 902 scm_is_pair (walk);
82dc9f57
MD
903 walk = SCM_CDR (walk))
904 {
7888309b 905 if (! scm_is_false (scm_equal_p (SCM_CAR (walk), item)))
82dc9f57
MD
906 {
907 *prev = SCM_CDR (walk);
908 break;
909 }
910 else
911 prev = SCM_CDRLOC (walk);
912 }
913
914 return lst;
915}
1bbd0b84 916#undef FUNC_NAME
82dc9f57 917
c614a00b
MD
918SCM_DEFINE (scm_filter, "filter", 2, 0, 0,
919 (SCM pred, SCM list),
920 "Return all the elements of 2nd arg @var{list} that satisfy predicate @var{pred}.\n"
921 "The list is not disordered -- elements that appear in the result list occur\n"
922 "in the same order as they occur in the argument list. The returned list may\n"
923 "share a common tail with the argument list. The dynamic order in which the\n"
924 "various applications of pred are made is not specified.\n\n"
925 "@lisp\n"
926 "(filter even? '(0 7 8 8 43 -4)) => (0 8 8 -4)\n"
927 "@end lisp")
928#define FUNC_NAME s_scm_filter
929{
c614a00b
MD
930 SCM walk;
931 SCM *prev;
932 SCM res = SCM_EOL;
6c9e8a53 933 SCM_ASSERT (scm_is_true (scm_procedure_p (pred)), pred, 1, FUNC_NAME);
c614a00b
MD
934 SCM_VALIDATE_LIST (2, list);
935
936 for (prev = &res, walk = list;
d2e53ed6 937 scm_is_pair (walk);
c614a00b
MD
938 walk = SCM_CDR (walk))
939 {
6c9e8a53 940 if (scm_is_true (scm_call_1 (pred, SCM_CAR (walk))))
c614a00b
MD
941 {
942 *prev = scm_cons (SCM_CAR (walk), SCM_EOL);
943 prev = SCM_CDRLOC (*prev);
944 }
945 }
946
947 return res;
948}
949#undef FUNC_NAME
950
951SCM_DEFINE (scm_filter_x, "filter!", 2, 0, 0,
952 (SCM pred, SCM list),
953 "Linear-update variant of @code{filter}.")
954#define FUNC_NAME s_scm_filter_x
955{
c614a00b
MD
956 SCM walk;
957 SCM *prev;
6c9e8a53 958 SCM_ASSERT (scm_is_true (scm_procedure_p (pred)), pred, 1, FUNC_NAME);
c614a00b
MD
959 SCM_VALIDATE_LIST (2, list);
960
961 for (prev = &list, walk = list;
d2e53ed6 962 scm_is_pair (walk);
c614a00b
MD
963 walk = SCM_CDR (walk))
964 {
6c9e8a53 965 if (scm_is_true (scm_call_1 (pred, SCM_CAR (walk))))
c614a00b
MD
966 prev = SCM_CDRLOC (walk);
967 else
968 *prev = SCM_CDR (walk);
969 }
970
971 return list;
972}
973#undef FUNC_NAME
82dc9f57 974
0f2d19dd 975\f
0f2d19dd
JB
976void
977scm_init_list ()
0f2d19dd 978{
a0599745 979#include "libguile/list.x"
0f2d19dd 980}
89e00824
ML
981
982/*
983 Local Variables:
984 c-file-style: "gnu"
985 End:
986*/