* Eliminated use of SCM_ASSERT to check for range errors.
[bpt/guile.git] / libguile / list.c
CommitLineData
f2c9fcb0 1/* Copyright (C) 1995,1996,1997, 2000 Free Software Foundation, Inc.
0f2d19dd
JB
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2, or (at your option)
6 * any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this software; see the file COPYING. If not, write to
82892bed
JB
15 * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
16 * Boston, MA 02111-1307 USA
0f2d19dd
JB
17 *
18 * As a special exception, the Free Software Foundation gives permission
19 * for additional uses of the text contained in its release of GUILE.
20 *
21 * The exception is that, if you link the GUILE library with other files
22 * to produce an executable, this does not by itself cause the
23 * resulting executable to be covered by the GNU General Public License.
24 * Your use of that executable is in no way restricted on account of
25 * linking the GUILE library code into it.
26 *
27 * This exception does not however invalidate any other reasons why
28 * the executable file might be covered by the GNU General Public License.
29 *
30 * This exception applies only to the code released by the
31 * Free Software Foundation under the name GUILE. If you copy
32 * code from other Free Software Foundation releases into a copy of
33 * GUILE, as the General Public License permits, the exception does
34 * not apply to the code that you add in this way. To avoid misleading
35 * anyone as to the status of such modified files, you must delete
36 * this exception notice from them.
37 *
38 * If you write modifications of your own for GUILE, it is your choice
39 * whether to permit this exception to apply to your modifications.
82892bed 40 * If you do not wish that, delete this exception notice. */
1bbd0b84
GB
41
42/* Software engineering face-lift by Greg J. Badros, 11-Dec-1999,
43 gjb@cs.washington.edu, http://www.cs.washington.edu/homes/gjb */
44
0f2d19dd
JB
45\f
46#include <stdio.h>
a0599745
MD
47#include "libguile/_scm.h"
48#include "libguile/eq.h"
20e6290e 49
a0599745
MD
50#include "libguile/validate.h"
51#include "libguile/list.h"
0f2d19dd
JB
52
53#ifdef __STDC__
54#include <stdarg.h>
55#define var_start(x, y) va_start(x, y)
56#else
57#include <varargs.h>
58#define var_start(x, y) va_start(x)
59#endif
60
61\f
df13742c 62/* creating lists */
0f2d19dd 63
0f2d19dd
JB
64SCM
65scm_listify (SCM elt, ...)
0f2d19dd
JB
66{
67 va_list foo;
2de14ecd
GB
68 SCM answer = SCM_EOL;
69 SCM *pos = &answer;
0f2d19dd
JB
70
71 var_start (foo, elt);
fbd485ba 72 while (! SCM_UNBNDP (elt))
0f2d19dd
JB
73 {
74 *pos = scm_cons (elt, SCM_EOL);
25d8012c 75 pos = SCM_CDRLOC (*pos);
0f2d19dd
JB
76 elt = va_arg (foo, SCM);
77 }
78 return answer;
79}
80
81
3b3b36dd 82SCM_DEFINE (scm_list, "list", 0, 0, 1,
1bbd0b84 83 (SCM objs),
b450f070 84 "Return a list containing OBJS, the arguments to `list'.")
1bbd0b84 85#define FUNC_NAME s_scm_list
0f2d19dd
JB
86{
87 return objs;
88}
1bbd0b84 89#undef FUNC_NAME
0f2d19dd
JB
90
91
26a379b2
MD
92#if (SCM_DEBUG_DEPRECATED == 0)
93
94SCM_REGISTER_PROC (s_list_star, "list*", 1, 0, 1, scm_cons_star);
95
96#endif /* SCM_DEBUG_DEPRECATED == 0 */
97
98SCM_DEFINE (scm_cons_star, "cons*", 1, 0, 1,
1bbd0b84 99 (SCM arg, SCM rest),
33d0abd7
MD
100 "Like `list', but the last arg provides the tail of the constructed list,\n"
101 "returning (cons ARG1 (cons ARG2 (cons ... ARGn))).\n"
102 "Requires at least one argument. If given one argument, that argument\n"
103 "is returned as result.\n"
104 "This function is called `list*' in some other Schemes and in Common LISP.")
26a379b2 105#define FUNC_NAME s_scm_cons_star
a610b8d9 106{
af45e3b0
DH
107 SCM_VALIDATE_REST_ARGUMENT (rest);
108 if (!SCM_NULLP (rest))
a610b8d9
MD
109 {
110 SCM prev = arg = scm_cons (arg, rest);
e1385ffc 111 while (SCM_NNULLP (SCM_CDR (rest)))
a610b8d9
MD
112 {
113 prev = rest;
114 rest = SCM_CDR (rest);
115 }
116 SCM_SETCDR (prev, SCM_CAR (rest));
117 }
118 return arg;
119}
1bbd0b84 120#undef FUNC_NAME
a610b8d9 121
0f2d19dd
JB
122
123\f
df13742c 124/* general questions about lists --- null?, list?, length, etc. */
0f2d19dd 125
3b3b36dd 126SCM_DEFINE (scm_null_p, "null?", 1, 0, 0,
1bbd0b84 127 (SCM x),
b450f070 128 "Return #t iff X is the empty list, else #f.")
1bbd0b84 129#define FUNC_NAME s_scm_null_p
0f2d19dd 130{
2de14ecd 131 return SCM_BOOL (SCM_NULLP (x));
0f2d19dd 132}
1bbd0b84 133#undef FUNC_NAME
0f2d19dd 134
2de14ecd 135
3b3b36dd 136SCM_DEFINE (scm_list_p, "list?", 1, 0, 0,
1bbd0b84 137 (SCM x),
b450f070 138 "Return #t iff X is a proper list, else #f.")
1bbd0b84 139#define FUNC_NAME s_scm_list_p
0f2d19dd 140{
2de14ecd 141 return SCM_BOOL (scm_ilength (x) >= 0);
0f2d19dd 142}
1bbd0b84 143#undef FUNC_NAME
0f2d19dd
JB
144
145
df13742c 146/* Return the length of SX, or -1 if it's not a proper list.
448a3bc2 147 This uses the "tortoise and hare" algorithm to detect "infinitely
df13742c
JB
148 long" lists (i.e. lists with cycles in their cdrs), and returns -1
149 if it does find one. */
0f2d19dd 150long
1bbd0b84 151scm_ilength(SCM sx)
0f2d19dd 152{
e1385ffc
GB
153 long i = 0;
154 SCM tortoise = sx;
155 SCM hare = sx;
df13742c 156
0f2d19dd 157 do {
e1385ffc 158 if (SCM_NULLP(hare)) return i;
ff467021 159 if (SCM_NCONSP(hare)) return -1;
df13742c 160 hare = SCM_CDR(hare);
0f2d19dd 161 i++;
e1385ffc 162 if (SCM_NULLP(hare)) return i;
ff467021 163 if (SCM_NCONSP(hare)) return -1;
df13742c 164 hare = SCM_CDR(hare);
0f2d19dd 165 i++;
448a3bc2
JB
166 /* For every two steps the hare takes, the tortoise takes one. */
167 tortoise = SCM_CDR(tortoise);
0f2d19dd 168 }
fbd485ba 169 while (! SCM_EQ_P (hare, tortoise));
df13742c 170
448a3bc2 171 /* If the tortoise ever catches the hare, then the list must contain
df13742c 172 a cycle. */
0f2d19dd
JB
173 return -1;
174}
175
2de14ecd 176
3b3b36dd 177SCM_DEFINE (scm_length, "length", 1, 0, 0,
1bbd0b84 178 (SCM lst),
b450f070 179 "Return the number of elements in list LST.")
1bbd0b84 180#define FUNC_NAME s_scm_length
0f2d19dd
JB
181{
182 int i;
3b3b36dd 183 SCM_VALIDATE_LIST_COPYLEN (1,lst,i);
0f2d19dd
JB
184 return SCM_MAKINUM (i);
185}
1bbd0b84 186#undef FUNC_NAME
0f2d19dd
JB
187
188
189\f
df13742c 190/* appending lists */
0f2d19dd 191
a1ec6916 192SCM_DEFINE (scm_append, "append", 0, 0, 1,
1bbd0b84 193 (SCM args),
7866a09b
GB
194 "Returns a list consisting of the elements of the first LIST\n"
195 "followed by the elements of the other LISTs.\n"
196 "\n"
197 " (append '(x) '(y)) => (x y)\n"
198 " (append '(a) '(b c d)) => (a b c d)\n"
199 " (append '(a (b)) '((c))) => (a (b) (c))\n"
200 "\n"
201 "The resulting list is always newly allocated, except that it shares\n"
202 "structure with the last LIST argument. The last argument may\n"
203 "actually be any object; an improper list results if the last\n"
204 "argument is not a proper list.\n"
205
206 " (append '(a b) '(c . d)) => (a b c . d)\n"
207 " (append '() 'a) => a\n")
1bbd0b84 208#define FUNC_NAME s_scm_append
0f2d19dd 209{
af45e3b0
DH
210 SCM_VALIDATE_REST_ARGUMENT (args);
211 if (SCM_NULLP (args)) {
212 return SCM_EOL;
213 } else {
214 SCM res = SCM_EOL;
215 SCM *lloc = &res;
216 SCM arg = SCM_CAR (args);
217 args = SCM_CDR (args);
218 while (!SCM_NULLP (args)) {
219 while (SCM_CONSP (arg)) {
220 *lloc = scm_cons (SCM_CAR (arg), SCM_EOL);
221 lloc = SCM_CDRLOC (*lloc);
222 arg = SCM_CDR (arg);
223 }
224 SCM_VALIDATE_NULL (SCM_ARGn, arg);
225 arg = SCM_CAR (args);
226 args = SCM_CDR (args);
227 };
228 *lloc = arg;
0f2d19dd
JB
229 return res;
230 }
0f2d19dd 231}
1bbd0b84 232#undef FUNC_NAME
0f2d19dd
JB
233
234
a1ec6916 235SCM_DEFINE (scm_append_x, "append!", 0, 0, 1,
1bbd0b84 236 (SCM args),
7866a09b
GB
237 "A destructive version of @code{append} (@pxref{Pairs and Lists,,,r4rs,\n"
238 "The Revised^4 Report on Scheme}). The cdr field of each list's final\n"
239 "pair is changed to point to the head of the next list, so no consing is\n"
240 "performed. Return a pointer to the mutated list.")
1bbd0b84 241#define FUNC_NAME s_scm_append_x
0f2d19dd 242{
af45e3b0
DH
243 SCM_VALIDATE_REST_ARGUMENT (args);
244 while (1) {
245 if (SCM_NULLP (args)) {
246 return SCM_EOL;
247 } else {
248 SCM arg = SCM_CAR (args);
249 args = SCM_CDR (args);
250 if (SCM_NULLP (args)) {
251 return arg;
252 } else if (!SCM_NULLP (arg)) {
253 SCM_VALIDATE_CONS (SCM_ARG1, arg);
254 SCM_SETCDR (scm_last_pair (arg), scm_append_x (args));
255 return arg;
256 }
257 }
258 }
0f2d19dd 259}
1bbd0b84 260#undef FUNC_NAME
0f2d19dd
JB
261
262
3b3b36dd 263SCM_DEFINE (scm_last_pair, "last-pair", 1, 0, 0,
e1385ffc 264 (SCM lst),
b380b885
MD
265 "Return a pointer to the last pair in @var{lst}, signalling an error if\n"
266 "@var{lst} is circular.")
1bbd0b84 267#define FUNC_NAME s_scm_last_pair
df13742c 268{
e1385ffc
GB
269 SCM tortoise = lst;
270 SCM hare = lst;
0f2d19dd 271
e1385ffc 272 if (SCM_NULLP (lst))
df13742c
JB
273 return SCM_EOL;
274
e1385ffc
GB
275 SCM_VALIDATE_CONS (SCM_ARG1, lst);
276 do {
277 SCM ahead = SCM_CDR(hare);
278 if (SCM_NCONSP(ahead)) return hare;
279 hare = ahead;
280 ahead = SCM_CDR(hare);
281 if (SCM_NCONSP(ahead)) return hare;
282 hare = ahead;
283 tortoise = SCM_CDR(tortoise);
df13742c 284 }
fbd485ba 285 while (! SCM_EQ_P (hare, tortoise));
5d2d2ffc 286 SCM_MISC_ERROR ("Circular structure in position 1: ~S", SCM_LIST1 (lst));
df13742c 287}
1bbd0b84 288#undef FUNC_NAME
df13742c
JB
289
290\f
291/* reversing lists */
0f2d19dd 292
a1ec6916 293SCM_DEFINE (scm_reverse, "reverse", 1, 0, 0,
e1385ffc 294 (SCM lst),
b450f070 295 "Return a new list that contains the elements of LST but in reverse order.")
e1385ffc
GB
296#define FUNC_NAME s_scm_reverse
297{
298 SCM result = SCM_EOL;
299 SCM tortoise = lst;
300 SCM hare = lst;
301
302 do {
303 if (SCM_NULLP(hare)) return result;
304 SCM_ASSERT(SCM_CONSP(hare), lst, 1, FUNC_NAME);
305 result = scm_cons (SCM_CAR (hare), result);
306 hare = SCM_CDR (hare);
307 if (SCM_NULLP(hare)) return result;
308 SCM_ASSERT(SCM_CONSP(hare), lst, 1, FUNC_NAME);
309 result = scm_cons (SCM_CAR (hare), result);
310 hare = SCM_CDR (hare);
311 tortoise = SCM_CDR (tortoise);
312 }
fbd485ba 313 while (! SCM_EQ_P (hare, tortoise));
5d2d2ffc 314 SCM_MISC_ERROR ("Circular structure in position 1: ~S", SCM_LIST1 (lst));
e1385ffc
GB
315}
316#undef FUNC_NAME
317
318SCM_DEFINE (scm_reverse_x, "reverse!", 1, 1, 0,
319 (SCM lst, SCM new_tail),
b380b885
MD
320 "A destructive version of @code{reverse} (@pxref{Pairs and Lists,,,r4rs,\n"
321 "The Revised^4 Report on Scheme}). The cdr of each cell in @var{lst} is\n"
322 "modified to point to the previous list element. Return a pointer to the\n"
323 "head of the reversed list.\n\n"
324 "Caveat: because the list is modified in place, the tail of the original\n"
325 "list now becomes its head, and the head of the original list now becomes\n"
326 "the tail. Therefore, the @var{lst} symbol to which the head of the\n"
327 "original list was bound now points to the tail. To ensure that the head\n"
328 "of the modified list is not lost, it is wise to save the return value of\n"
329 "@code{reverse!}")
1bbd0b84 330#define FUNC_NAME s_scm_reverse_x
0f2d19dd 331{
e1385ffc 332 SCM_ASSERT (scm_ilength (lst) >= 0, lst, SCM_ARG1, FUNC_NAME);
3946f0de
MD
333 if (SCM_UNBNDP (new_tail))
334 new_tail = SCM_EOL;
335 else
1bbd0b84 336 SCM_ASSERT (scm_ilength (new_tail) >= 0, new_tail, SCM_ARG2, FUNC_NAME);
0f2d19dd 337
e1385ffc 338 while (SCM_NNULLP (lst))
3946f0de 339 {
e1385ffc
GB
340 SCM old_tail = SCM_CDR (lst);
341 SCM_SETCDR (lst, new_tail);
342 new_tail = lst;
343 lst = old_tail;
3946f0de
MD
344 }
345 return new_tail;
0f2d19dd 346}
1bbd0b84 347#undef FUNC_NAME
0f2d19dd 348
0f2d19dd 349\f
685c0d71 350
df13742c 351/* indexing lists by element number */
0f2d19dd 352
3b3b36dd 353SCM_DEFINE (scm_list_ref, "list-ref", 2, 0, 0,
685c0d71
DH
354 (SCM list, SCM k),
355 "Return the Kth element from LIST.")
1bbd0b84
GB
356#define FUNC_NAME s_scm_list_ref
357{
685c0d71
DH
358 SCM lst = list;
359 unsigned long int i;
3b3b36dd 360 SCM_VALIDATE_INUM_MIN_COPY (2,k,0,i);
685c0d71
DH
361 while (SCM_CONSP (lst)) {
362 if (i == 0)
363 return SCM_CAR (lst);
364 else {
365 --i;
366 lst = SCM_CDR (lst);
367 }
368 };
369 if (SCM_NULLP (lst))
370 SCM_OUT_OF_RANGE (2, k);
371 else
372 SCM_WRONG_TYPE_ARG (1, list);
0f2d19dd 373}
1bbd0b84 374#undef FUNC_NAME
0f2d19dd 375
685c0d71 376
3b3b36dd 377SCM_DEFINE (scm_list_set_x, "list-set!", 3, 0, 0,
685c0d71
DH
378 (SCM list, SCM k, SCM val),
379 "Set the @var{k}th element of @var{list} to @var{val}.")
1bbd0b84
GB
380#define FUNC_NAME s_scm_list_set_x
381{
685c0d71
DH
382 SCM lst = list;
383 unsigned long int i;
3b3b36dd 384 SCM_VALIDATE_INUM_MIN_COPY (2,k,0,i);
685c0d71
DH
385 while (SCM_CONSP (lst)) {
386 if (i == 0) {
387 SCM_SETCAR (lst, val);
388 return val;
389 } else {
390 --i;
391 lst = SCM_CDR (lst);
392 }
393 };
394 if (SCM_NULLP (lst))
395 SCM_OUT_OF_RANGE (2, k);
396 else
397 SCM_WRONG_TYPE_ARG (1, list);
0f2d19dd 398}
1bbd0b84 399#undef FUNC_NAME
0f2d19dd
JB
400
401
1bbd0b84
GB
402SCM_REGISTER_PROC(s_list_cdr_ref, "list-cdr-ref", 2, 0, 0, scm_list_tail);
403
3b3b36dd 404SCM_DEFINE (scm_list_tail, "list-tail", 2, 0, 0,
1bbd0b84 405 (SCM lst, SCM k),
b380b885
MD
406 "Return the \"tail\" of @var{lst} beginning with its @var{k}th element.\n"
407 "The first element of the list is considered to be element 0.\n\n"
408 "@code{list-cdr-ref} and @code{list-tail} are identical. It may help to\n"
409 "think of @code{list-cdr-ref} as accessing the @var{k}th cdr of the list,\n"
410 "or returning the results of cdring @var{k} times down @var{lst}.")
1bbd0b84 411#define FUNC_NAME s_scm_list_tail
df13742c
JB
412{
413 register long i;
3b3b36dd 414 SCM_VALIDATE_INUM_MIN_COPY (2,k,0,i);
df13742c 415 while (i-- > 0) {
3b3b36dd 416 SCM_VALIDATE_CONS (1,lst);
df13742c
JB
417 lst = SCM_CDR(lst);
418 }
419 return lst;
420}
1bbd0b84 421#undef FUNC_NAME
df13742c 422
0f2d19dd 423
3b3b36dd 424SCM_DEFINE (scm_list_cdr_set_x, "list-cdr-set!", 3, 0, 0,
685c0d71
DH
425 (SCM list, SCM k, SCM val),
426 "Set the @var{k}th cdr of @var{list} to @var{val}.")
1bbd0b84
GB
427#define FUNC_NAME s_scm_list_cdr_set_x
428{
685c0d71
DH
429 SCM lst = list;
430 unsigned long int i;
3b3b36dd 431 SCM_VALIDATE_INUM_MIN_COPY (2,k,0,i);
685c0d71
DH
432 while (SCM_CONSP (lst)) {
433 if (i == 0) {
434 SCM_SETCDR (lst, val);
435 return val;
436 } else {
437 --i;
438 lst = SCM_CDR (lst);
439 }
440 };
441 if (SCM_NULLP (lst))
442 SCM_OUT_OF_RANGE (2, k);
443 else
444 SCM_WRONG_TYPE_ARG (1, list);
0f2d19dd 445}
1bbd0b84 446#undef FUNC_NAME
0f2d19dd
JB
447
448
449\f
df13742c 450/* copying lists, perhaps partially */
0f2d19dd 451
3b3b36dd 452SCM_DEFINE (scm_list_head, "list-head", 2, 0, 0,
1bbd0b84 453 (SCM lst, SCM k),
b380b885
MD
454 "Copy the first @var{k} elements from @var{lst} into a new list, and\n"
455 "return it.")
1bbd0b84 456#define FUNC_NAME s_scm_list_head
0f2d19dd
JB
457{
458 SCM answer;
459 SCM * pos;
460 register long i;
461
3b3b36dd 462 SCM_VALIDATE_INUM_MIN_COPY (2,k,0,i);
0f2d19dd
JB
463 answer = SCM_EOL;
464 pos = &answer;
0f2d19dd
JB
465 while (i-- > 0)
466 {
3b3b36dd 467 SCM_VALIDATE_CONS (1,lst);
0f2d19dd 468 *pos = scm_cons (SCM_CAR (lst), SCM_EOL);
25d8012c 469 pos = SCM_CDRLOC (*pos);
0f2d19dd
JB
470 lst = SCM_CDR(lst);
471 }
472 return answer;
473}
1bbd0b84 474#undef FUNC_NAME
0f2d19dd
JB
475
476
a1ec6916 477SCM_DEFINE (scm_list_copy, "list-copy", 1, 0, 0,
1bbd0b84 478 (SCM lst),
b380b885 479 "Return a (newly-created) copy of @var{lst}.")
1bbd0b84 480#define FUNC_NAME s_scm_list_copy
df13742c
JB
481{
482 SCM newlst;
483 SCM * fill_here;
484 SCM from_here;
485
486 newlst = SCM_EOL;
487 fill_here = &newlst;
488 from_here = lst;
489
0c95b57d 490 while (SCM_CONSP (from_here))
df13742c
JB
491 {
492 SCM c;
493 c = scm_cons (SCM_CAR (from_here), SCM_CDR (from_here));
494 *fill_here = c;
25d8012c 495 fill_here = SCM_CDRLOC (c);
df13742c
JB
496 from_here = SCM_CDR (from_here);
497 }
498 return newlst;
499}
1bbd0b84 500#undef FUNC_NAME
df13742c 501
0f2d19dd 502\f
df13742c
JB
503/* membership tests (memq, memv, etc.) */
504
a1ec6916 505SCM_DEFINE (scm_sloppy_memq, "sloppy-memq", 2, 0, 0,
1bbd0b84 506 (SCM x, SCM lst),
b450f070
GB
507 "This procedure behaves like @code{memq}, but does no type or error checking.\n"
508 "Its use is recommended only in writing Guile internals,\n"
509 "not for high-level Scheme programs.")
1bbd0b84 510#define FUNC_NAME s_scm_sloppy_memq
0f2d19dd 511{
0c95b57d 512 for(; SCM_CONSP (lst); lst = SCM_CDR(lst))
0f2d19dd 513 {
fbd485ba 514 if (SCM_EQ_P (SCM_CAR (lst), x))
0f2d19dd
JB
515 return lst;
516 }
517 return lst;
518}
1bbd0b84 519#undef FUNC_NAME
0f2d19dd
JB
520
521
a1ec6916 522SCM_DEFINE (scm_sloppy_memv, "sloppy-memv", 2, 0, 0,
1bbd0b84 523 (SCM x, SCM lst),
b450f070
GB
524 "This procedure behaves like @code{memv}, but does no type or error checking.\n"
525 "Its use is recommended only in writing Guile internals,\n"
526 "not for high-level Scheme programs.")
1bbd0b84 527#define FUNC_NAME s_scm_sloppy_memv
0f2d19dd 528{
0c95b57d 529 for(; SCM_CONSP (lst); lst = SCM_CDR(lst))
0f2d19dd 530 {
fbd485ba 531 if (! SCM_FALSEP (scm_eqv_p (SCM_CAR (lst), x)))
0f2d19dd
JB
532 return lst;
533 }
534 return lst;
535}
1bbd0b84 536#undef FUNC_NAME
0f2d19dd
JB
537
538
a1ec6916 539SCM_DEFINE (scm_sloppy_member, "sloppy-member", 2, 0, 0,
1bbd0b84 540 (SCM x, SCM lst),
b450f070
GB
541 "This procedure behaves like @code{member}, but does no type or error checking.\n"
542 "Its use is recommended only in writing Guile internals,\n"
543 "not for high-level Scheme programs.")
1bbd0b84 544#define FUNC_NAME s_scm_sloppy_member
0f2d19dd 545{
0c95b57d 546 for(; SCM_CONSP (lst); lst = SCM_CDR(lst))
0f2d19dd 547 {
fbd485ba 548 if (! SCM_FALSEP (scm_equal_p (SCM_CAR (lst), x)))
0f2d19dd
JB
549 return lst;
550 }
551 return lst;
552}
1bbd0b84 553#undef FUNC_NAME
0f2d19dd
JB
554
555
556
3b3b36dd 557SCM_DEFINE (scm_memq, "memq", 2, 0, 0,
1bbd0b84 558 (SCM x, SCM lst),
b450f070
GB
559 "Return the first sublist of LST whose car is `eq?' to X\n"
560 "where the sublists of LST are the non-empty lists returned\n"
561 "by `(list-tail LST K)' for K less than the length of LST. If\n"
562 "X does not occur in LST, then `#f' (not the empty list) is\n"
563 "returned.")
1bbd0b84 564#define FUNC_NAME s_scm_memq
0f2d19dd
JB
565{
566 SCM answer;
3b3b36dd 567 SCM_VALIDATE_LIST (2,lst);
0f2d19dd 568 answer = scm_sloppy_memq (x, lst);
fbd485ba 569 return (SCM_NULLP (answer)) ? SCM_BOOL_F : answer;
0f2d19dd 570}
1bbd0b84 571#undef FUNC_NAME
0f2d19dd
JB
572
573
574
3b3b36dd 575SCM_DEFINE (scm_memv, "memv", 2, 0, 0,
1bbd0b84 576 (SCM x, SCM lst),
b450f070
GB
577 "Return the first sublist of LST whose car is `eqv?' to X\n"
578 "where the sublists of LST are the non-empty lists returned\n"
579 "by `(list-tail LST K)' for K less than the length of LST. If\n"
580 "X does not occur in LST, then `#f' (not the empty list) is\n"
581 "returned.")
1bbd0b84 582#define FUNC_NAME s_scm_memv
0f2d19dd
JB
583{
584 SCM answer;
3b3b36dd 585 SCM_VALIDATE_LIST (2,lst);
0f2d19dd 586 answer = scm_sloppy_memv (x, lst);
fbd485ba 587 return (SCM_NULLP (answer)) ? SCM_BOOL_F : answer;
0f2d19dd 588}
1bbd0b84 589#undef FUNC_NAME
0f2d19dd
JB
590
591
3b3b36dd 592SCM_DEFINE (scm_member, "member", 2, 0, 0,
1bbd0b84 593 (SCM x, SCM lst),
b450f070
GB
594 "Return the first sublist of LST whose car is `equal?' to X\n"
595 "where the sublists of LST are the non-empty lists returned\n"
596 "by `(list-tail LST K)' for K less than the length of LST. If\n"
597 "X does not occur in LST, then `#f' (not the empty list) is\n"
598 "returned.")
1bbd0b84 599#define FUNC_NAME s_scm_member
0f2d19dd
JB
600{
601 SCM answer;
3b3b36dd 602 SCM_VALIDATE_LIST (2,lst);
0f2d19dd 603 answer = scm_sloppy_member (x, lst);
fbd485ba 604 return (SCM_NULLP (answer)) ? SCM_BOOL_F : answer;
0f2d19dd 605}
1bbd0b84 606#undef FUNC_NAME
0f2d19dd
JB
607
608
609\f
df13742c 610/* deleting elements from a list (delq, etc.) */
0f2d19dd 611
3b3b36dd 612SCM_DEFINE (scm_delq_x, "delq!", 2, 0, 0,
1bbd0b84 613 (SCM item, SCM lst),
b380b885
MD
614 "@deffnx primitive delv! item lst\n"
615 "@deffnx primitive delete! item lst\n"
616 "These procedures are destructive versions of @code{delq}, @code{delv}\n"
617 "and @code{delete}: they modify the pointers in the existing @var{lst}\n"
618 "rather than creating a new list. Caveat evaluator: Like other\n"
619 "destructive list functions, these functions cannot modify the binding of\n"
620 "@var{lst}, and so cannot be used to delete the first element of\n"
621 "@var{lst} destructively.")
1bbd0b84 622#define FUNC_NAME s_scm_delq_x
0f2d19dd 623{
164271a1
JB
624 SCM walk;
625 SCM *prev;
0f2d19dd 626
164271a1 627 for (prev = &lst, walk = lst;
0c95b57d 628 SCM_CONSP (walk);
164271a1 629 walk = SCM_CDR (walk))
0f2d19dd 630 {
fbd485ba 631 if (SCM_EQ_P (SCM_CAR (walk), item))
164271a1
JB
632 *prev = SCM_CDR (walk);
633 else
634 prev = SCM_CDRLOC (walk);
0f2d19dd 635 }
164271a1
JB
636
637 return lst;
0f2d19dd 638}
1bbd0b84 639#undef FUNC_NAME
0f2d19dd
JB
640
641
3b3b36dd 642SCM_DEFINE (scm_delv_x, "delv!", 2, 0, 0,
1bbd0b84 643 (SCM item, SCM lst),
b450f070 644 "Destructively remove all elements from LST that are `eqv?' to ITEM.")
1bbd0b84 645#define FUNC_NAME s_scm_delv_x
0f2d19dd 646{
164271a1
JB
647 SCM walk;
648 SCM *prev;
0f2d19dd 649
164271a1 650 for (prev = &lst, walk = lst;
0c95b57d 651 SCM_CONSP (walk);
164271a1 652 walk = SCM_CDR (walk))
0f2d19dd 653 {
fbd485ba 654 if (! SCM_FALSEP (scm_eqv_p (SCM_CAR (walk), item)))
164271a1
JB
655 *prev = SCM_CDR (walk);
656 else
657 prev = SCM_CDRLOC (walk);
0f2d19dd 658 }
164271a1
JB
659
660 return lst;
0f2d19dd 661}
1bbd0b84 662#undef FUNC_NAME
0f2d19dd
JB
663
664
665
3b3b36dd 666SCM_DEFINE (scm_delete_x, "delete!", 2, 0, 0,
1bbd0b84 667 (SCM item, SCM lst),
b450f070 668 "Destructively remove all elements from LST that are `equal?' to ITEM.")
1bbd0b84 669#define FUNC_NAME s_scm_delete_x
0f2d19dd 670{
164271a1
JB
671 SCM walk;
672 SCM *prev;
0f2d19dd 673
164271a1 674 for (prev = &lst, walk = lst;
0c95b57d 675 SCM_CONSP (walk);
164271a1 676 walk = SCM_CDR (walk))
0f2d19dd 677 {
fbd485ba 678 if (! SCM_FALSEP (scm_equal_p (SCM_CAR (walk), item)))
164271a1
JB
679 *prev = SCM_CDR (walk);
680 else
681 prev = SCM_CDRLOC (walk);
0f2d19dd 682 }
164271a1
JB
683
684 return lst;
0f2d19dd 685}
1bbd0b84 686#undef FUNC_NAME
0f2d19dd
JB
687
688
689\f
690
0f2d19dd 691
a1ec6916 692SCM_DEFINE (scm_delq, "delq", 2, 0, 0,
1bbd0b84 693 (SCM item, SCM lst),
b450f070
GB
694 "Return a newly-created copy of @var{lst} with elements `eq?' to @var{item} removed.\n"
695 "This procedure mirrors @code{memq}:\n"
b380b885 696 "@code{delq} compares elements of @var{lst} against @var{item} with\n"
b450f070 697 "@code{eq?}.")
1bbd0b84 698#define FUNC_NAME s_scm_delq
0f2d19dd 699{
1bbd0b84 700 SCM copy = scm_list_copy (lst);
0f2d19dd
JB
701 return scm_delq_x (item, copy);
702}
1bbd0b84 703#undef FUNC_NAME
0f2d19dd 704
a1ec6916 705SCM_DEFINE (scm_delv, "delv", 2, 0, 0,
1bbd0b84 706 (SCM item, SCM lst),
b450f070
GB
707 "Return a newly-created copy of @var{lst} with elements `eqv?' to @var{item} removed.\n"
708 "This procedure mirrors @code{memv}:\n"
709 "@code{delv} compares elements of @var{lst} against @var{item} with\n"
710 "@code{eqv?}.")
1bbd0b84 711#define FUNC_NAME s_scm_delv
0f2d19dd 712{
1bbd0b84 713 SCM copy = scm_list_copy (lst);
0f2d19dd
JB
714 return scm_delv_x (item, copy);
715}
1bbd0b84 716#undef FUNC_NAME
0f2d19dd 717
a1ec6916 718SCM_DEFINE (scm_delete, "delete", 2, 0, 0,
1bbd0b84 719 (SCM item, SCM lst),
b450f070
GB
720 "Return a newly-created copy of @var{lst} with elements `equal?' to @var{item} removed.\n"
721 "This procedure mirrors @code{member}:\n"
722 "@code{delete} compares elements of @var{lst} against @var{item} with\n"
723 "@code{equal?}.")
1bbd0b84 724#define FUNC_NAME s_scm_delete
0f2d19dd 725{
1bbd0b84 726 SCM copy = scm_list_copy (lst);
0f2d19dd
JB
727 return scm_delete_x (item, copy);
728}
1bbd0b84 729#undef FUNC_NAME
0f2d19dd
JB
730
731
3b3b36dd 732SCM_DEFINE (scm_delq1_x, "delq1!", 2, 0, 0,
1bbd0b84 733 (SCM item, SCM lst),
8507b88c
GB
734 "Like `delq!', but only deletes the first occurrence of ITEM from LST.\n"
735 "Tests for equality using `eq?'. See also `delv1!' and `delete1!'.")
1bbd0b84 736#define FUNC_NAME s_scm_delq1_x
82dc9f57
MD
737{
738 SCM walk;
739 SCM *prev;
740
741 for (prev = &lst, walk = lst;
0c95b57d 742 SCM_CONSP (walk);
82dc9f57
MD
743 walk = SCM_CDR (walk))
744 {
fbd485ba 745 if (SCM_EQ_P (SCM_CAR (walk), item))
82dc9f57
MD
746 {
747 *prev = SCM_CDR (walk);
748 break;
749 }
750 else
751 prev = SCM_CDRLOC (walk);
752 }
753
754 return lst;
755}
1bbd0b84 756#undef FUNC_NAME
82dc9f57
MD
757
758
3b3b36dd 759SCM_DEFINE (scm_delv1_x, "delv1!", 2, 0, 0,
8507b88c
GB
760 (SCM item, SCM lst),
761 "Like `delv!', but only deletes the first occurrence of ITEM from LST.\n"
762 "Tests for equality using `eqv?'. See also `delq1!' and `delete1!'.")
1bbd0b84 763#define FUNC_NAME s_scm_delv1_x
82dc9f57
MD
764{
765 SCM walk;
766 SCM *prev;
767
768 for (prev = &lst, walk = lst;
0c95b57d 769 SCM_CONSP (walk);
82dc9f57
MD
770 walk = SCM_CDR (walk))
771 {
fbd485ba 772 if (! SCM_FALSEP (scm_eqv_p (SCM_CAR (walk), item)))
82dc9f57
MD
773 {
774 *prev = SCM_CDR (walk);
775 break;
776 }
777 else
778 prev = SCM_CDRLOC (walk);
779 }
780
781 return lst;
782}
1bbd0b84 783#undef FUNC_NAME
82dc9f57
MD
784
785
3b3b36dd 786SCM_DEFINE (scm_delete1_x, "delete1!", 2, 0, 0,
8507b88c
GB
787 (SCM item, SCM lst),
788 "Like `delete!', but only deletes the first occurrence of ITEM from LST.\n"
789 "Tests for equality using `equal?'. See also `delq1!' and `delv1!'.")
1bbd0b84 790#define FUNC_NAME s_scm_delete1_x
82dc9f57
MD
791{
792 SCM walk;
793 SCM *prev;
794
795 for (prev = &lst, walk = lst;
0c95b57d 796 SCM_CONSP (walk);
82dc9f57
MD
797 walk = SCM_CDR (walk))
798 {
fbd485ba 799 if (! SCM_FALSEP (scm_equal_p (SCM_CAR (walk), item)))
82dc9f57
MD
800 {
801 *prev = SCM_CDR (walk);
802 break;
803 }
804 else
805 prev = SCM_CDRLOC (walk);
806 }
807
808 return lst;
809}
1bbd0b84 810#undef FUNC_NAME
82dc9f57
MD
811
812
0f2d19dd 813\f
0f2d19dd
JB
814void
815scm_init_list ()
0f2d19dd 816{
a0599745 817#include "libguile/list.x"
0f2d19dd 818}
89e00824
ML
819
820/*
821 Local Variables:
822 c-file-style: "gnu"
823 End:
824*/