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