* gc.c (scm_protect_object): Updated comment.
[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
a1ec6916 92SCM_DEFINE (scm_list_star, "list*", 1, 0, 1,
1bbd0b84 93 (SCM arg, SCM rest),
79494f15
DH
94 "Works like `list' except that it returns an improper list of\n"
95 "the arguments, where the last argument is the cdr of the last\n"
96 "pair. If there is only one argument then the result is just\n"
97 "that argument. Sometimes this function is called cons*.")
1bbd0b84 98#define FUNC_NAME s_scm_list_star
a610b8d9 99{
af45e3b0
DH
100 SCM_VALIDATE_REST_ARGUMENT (rest);
101 if (!SCM_NULLP (rest))
a610b8d9
MD
102 {
103 SCM prev = arg = scm_cons (arg, rest);
e1385ffc 104 while (SCM_NNULLP (SCM_CDR (rest)))
a610b8d9
MD
105 {
106 prev = rest;
107 rest = SCM_CDR (rest);
108 }
109 SCM_SETCDR (prev, SCM_CAR (rest));
110 }
111 return arg;
112}
1bbd0b84 113#undef FUNC_NAME
a610b8d9 114
0f2d19dd
JB
115
116\f
df13742c 117/* general questions about lists --- null?, list?, length, etc. */
0f2d19dd 118
3b3b36dd 119SCM_DEFINE (scm_null_p, "null?", 1, 0, 0,
1bbd0b84 120 (SCM x),
b450f070 121 "Return #t iff X is the empty list, else #f.")
1bbd0b84 122#define FUNC_NAME s_scm_null_p
0f2d19dd 123{
2de14ecd 124 return SCM_BOOL (SCM_NULLP (x));
0f2d19dd 125}
1bbd0b84 126#undef FUNC_NAME
0f2d19dd 127
2de14ecd 128
3b3b36dd 129SCM_DEFINE (scm_list_p, "list?", 1, 0, 0,
1bbd0b84 130 (SCM x),
b450f070 131 "Return #t iff X is a proper list, else #f.")
1bbd0b84 132#define FUNC_NAME s_scm_list_p
0f2d19dd 133{
2de14ecd 134 return SCM_BOOL (scm_ilength (x) >= 0);
0f2d19dd 135}
1bbd0b84 136#undef FUNC_NAME
0f2d19dd
JB
137
138
df13742c 139/* Return the length of SX, or -1 if it's not a proper list.
448a3bc2 140 This uses the "tortoise and hare" algorithm to detect "infinitely
df13742c
JB
141 long" lists (i.e. lists with cycles in their cdrs), and returns -1
142 if it does find one. */
0f2d19dd 143long
1bbd0b84 144scm_ilength(SCM sx)
0f2d19dd 145{
e1385ffc
GB
146 long i = 0;
147 SCM tortoise = sx;
148 SCM hare = sx;
df13742c 149
0f2d19dd 150 do {
e1385ffc 151 if (SCM_NULLP(hare)) return i;
ff467021 152 if (SCM_NCONSP(hare)) return -1;
df13742c 153 hare = SCM_CDR(hare);
0f2d19dd 154 i++;
e1385ffc 155 if (SCM_NULLP(hare)) return i;
ff467021 156 if (SCM_NCONSP(hare)) return -1;
df13742c 157 hare = SCM_CDR(hare);
0f2d19dd 158 i++;
448a3bc2
JB
159 /* For every two steps the hare takes, the tortoise takes one. */
160 tortoise = SCM_CDR(tortoise);
0f2d19dd 161 }
fbd485ba 162 while (! SCM_EQ_P (hare, tortoise));
df13742c 163
448a3bc2 164 /* If the tortoise ever catches the hare, then the list must contain
df13742c 165 a cycle. */
0f2d19dd
JB
166 return -1;
167}
168
2de14ecd 169
3b3b36dd 170SCM_DEFINE (scm_length, "length", 1, 0, 0,
1bbd0b84 171 (SCM lst),
b450f070 172 "Return the number of elements in list LST.")
1bbd0b84 173#define FUNC_NAME s_scm_length
0f2d19dd
JB
174{
175 int i;
3b3b36dd 176 SCM_VALIDATE_LIST_COPYLEN (1,lst,i);
0f2d19dd
JB
177 return SCM_MAKINUM (i);
178}
1bbd0b84 179#undef FUNC_NAME
0f2d19dd
JB
180
181
182\f
df13742c 183/* appending lists */
0f2d19dd 184
a1ec6916 185SCM_DEFINE (scm_append, "append", 0, 0, 1,
1bbd0b84 186 (SCM args),
7866a09b
GB
187 "Returns a list consisting of the elements of the first LIST\n"
188 "followed by the elements of the other LISTs.\n"
189 "\n"
190 " (append '(x) '(y)) => (x y)\n"
191 " (append '(a) '(b c d)) => (a b c d)\n"
192 " (append '(a (b)) '((c))) => (a (b) (c))\n"
193 "\n"
194 "The resulting list is always newly allocated, except that it shares\n"
195 "structure with the last LIST argument. The last argument may\n"
196 "actually be any object; an improper list results if the last\n"
197 "argument is not a proper list.\n"
198
199 " (append '(a b) '(c . d)) => (a b c . d)\n"
200 " (append '() 'a) => a\n")
1bbd0b84 201#define FUNC_NAME s_scm_append
0f2d19dd 202{
af45e3b0
DH
203 SCM_VALIDATE_REST_ARGUMENT (args);
204 if (SCM_NULLP (args)) {
205 return SCM_EOL;
206 } else {
207 SCM res = SCM_EOL;
208 SCM *lloc = &res;
209 SCM arg = SCM_CAR (args);
210 args = SCM_CDR (args);
211 while (!SCM_NULLP (args)) {
212 while (SCM_CONSP (arg)) {
213 *lloc = scm_cons (SCM_CAR (arg), SCM_EOL);
214 lloc = SCM_CDRLOC (*lloc);
215 arg = SCM_CDR (arg);
216 }
217 SCM_VALIDATE_NULL (SCM_ARGn, arg);
218 arg = SCM_CAR (args);
219 args = SCM_CDR (args);
220 };
221 *lloc = arg;
0f2d19dd
JB
222 return res;
223 }
0f2d19dd 224}
1bbd0b84 225#undef FUNC_NAME
0f2d19dd
JB
226
227
a1ec6916 228SCM_DEFINE (scm_append_x, "append!", 0, 0, 1,
1bbd0b84 229 (SCM args),
7866a09b
GB
230 "A destructive version of @code{append} (@pxref{Pairs and Lists,,,r4rs,\n"
231 "The Revised^4 Report on Scheme}). The cdr field of each list's final\n"
232 "pair is changed to point to the head of the next list, so no consing is\n"
233 "performed. Return a pointer to the mutated list.")
1bbd0b84 234#define FUNC_NAME s_scm_append_x
0f2d19dd 235{
af45e3b0
DH
236 SCM_VALIDATE_REST_ARGUMENT (args);
237 while (1) {
238 if (SCM_NULLP (args)) {
239 return SCM_EOL;
240 } else {
241 SCM arg = SCM_CAR (args);
242 args = SCM_CDR (args);
243 if (SCM_NULLP (args)) {
244 return arg;
245 } else if (!SCM_NULLP (arg)) {
246 SCM_VALIDATE_CONS (SCM_ARG1, arg);
247 SCM_SETCDR (scm_last_pair (arg), scm_append_x (args));
248 return arg;
249 }
250 }
251 }
0f2d19dd 252}
1bbd0b84 253#undef FUNC_NAME
0f2d19dd
JB
254
255
3b3b36dd 256SCM_DEFINE (scm_last_pair, "last-pair", 1, 0, 0,
e1385ffc 257 (SCM lst),
b380b885
MD
258 "Return a pointer to the last pair in @var{lst}, signalling an error if\n"
259 "@var{lst} is circular.")
1bbd0b84 260#define FUNC_NAME s_scm_last_pair
df13742c 261{
e1385ffc
GB
262 SCM tortoise = lst;
263 SCM hare = lst;
0f2d19dd 264
e1385ffc 265 if (SCM_NULLP (lst))
df13742c
JB
266 return SCM_EOL;
267
e1385ffc
GB
268 SCM_VALIDATE_CONS (SCM_ARG1, lst);
269 do {
270 SCM ahead = SCM_CDR(hare);
271 if (SCM_NCONSP(ahead)) return hare;
272 hare = ahead;
273 ahead = SCM_CDR(hare);
274 if (SCM_NCONSP(ahead)) return hare;
275 hare = ahead;
276 tortoise = SCM_CDR(tortoise);
df13742c 277 }
fbd485ba 278 while (! SCM_EQ_P (hare, tortoise));
5d2d2ffc 279 SCM_MISC_ERROR ("Circular structure in position 1: ~S", SCM_LIST1 (lst));
df13742c 280}
1bbd0b84 281#undef FUNC_NAME
df13742c
JB
282
283\f
284/* reversing lists */
0f2d19dd 285
a1ec6916 286SCM_DEFINE (scm_reverse, "reverse", 1, 0, 0,
e1385ffc 287 (SCM lst),
b450f070 288 "Return a new list that contains the elements of LST but in reverse order.")
e1385ffc
GB
289#define FUNC_NAME s_scm_reverse
290{
291 SCM result = SCM_EOL;
292 SCM tortoise = lst;
293 SCM hare = lst;
294
295 do {
296 if (SCM_NULLP(hare)) return result;
297 SCM_ASSERT(SCM_CONSP(hare), lst, 1, FUNC_NAME);
298 result = scm_cons (SCM_CAR (hare), result);
299 hare = SCM_CDR (hare);
300 if (SCM_NULLP(hare)) return result;
301 SCM_ASSERT(SCM_CONSP(hare), lst, 1, FUNC_NAME);
302 result = scm_cons (SCM_CAR (hare), result);
303 hare = SCM_CDR (hare);
304 tortoise = SCM_CDR (tortoise);
305 }
fbd485ba 306 while (! SCM_EQ_P (hare, tortoise));
5d2d2ffc 307 SCM_MISC_ERROR ("Circular structure in position 1: ~S", SCM_LIST1 (lst));
e1385ffc
GB
308}
309#undef FUNC_NAME
310
311SCM_DEFINE (scm_reverse_x, "reverse!", 1, 1, 0,
312 (SCM lst, SCM new_tail),
b380b885
MD
313 "A destructive version of @code{reverse} (@pxref{Pairs and Lists,,,r4rs,\n"
314 "The Revised^4 Report on Scheme}). The cdr of each cell in @var{lst} is\n"
315 "modified to point to the previous list element. Return a pointer to the\n"
316 "head of the reversed list.\n\n"
317 "Caveat: because the list is modified in place, the tail of the original\n"
318 "list now becomes its head, and the head of the original list now becomes\n"
319 "the tail. Therefore, the @var{lst} symbol to which the head of the\n"
320 "original list was bound now points to the tail. To ensure that the head\n"
321 "of the modified list is not lost, it is wise to save the return value of\n"
322 "@code{reverse!}")
1bbd0b84 323#define FUNC_NAME s_scm_reverse_x
0f2d19dd 324{
e1385ffc 325 SCM_ASSERT (scm_ilength (lst) >= 0, lst, SCM_ARG1, FUNC_NAME);
3946f0de
MD
326 if (SCM_UNBNDP (new_tail))
327 new_tail = SCM_EOL;
328 else
1bbd0b84 329 SCM_ASSERT (scm_ilength (new_tail) >= 0, new_tail, SCM_ARG2, FUNC_NAME);
0f2d19dd 330
e1385ffc 331 while (SCM_NNULLP (lst))
3946f0de 332 {
e1385ffc
GB
333 SCM old_tail = SCM_CDR (lst);
334 SCM_SETCDR (lst, new_tail);
335 new_tail = lst;
336 lst = old_tail;
3946f0de
MD
337 }
338 return new_tail;
0f2d19dd 339}
1bbd0b84 340#undef FUNC_NAME
0f2d19dd
JB
341
342
343\f
df13742c 344/* indexing lists by element number */
0f2d19dd 345
3b3b36dd 346SCM_DEFINE (scm_list_ref, "list-ref", 2, 0, 0,
1bbd0b84 347 (SCM lst, SCM k),
b450f070 348 "Return the Kth element from list LST.")
1bbd0b84
GB
349#define FUNC_NAME s_scm_list_ref
350{
351 register long i;
3b3b36dd 352 SCM_VALIDATE_INUM_MIN_COPY (2,k,0,i);
1bbd0b84 353 while (i-- > 0) {
0c95b57d 354 SCM_ASRTGO(SCM_CONSP(lst), erout);
1bbd0b84
GB
355 lst = SCM_CDR(lst);
356 }
357 erout:
0c95b57d 358 SCM_ASSERT(SCM_CONSP(lst),
1bbd0b84
GB
359 SCM_NULLP(lst)?k:lst, SCM_NULLP(lst)?SCM_OUTOFRANGE:SCM_ARG1, FUNC_NAME);
360 return SCM_CAR(lst);
0f2d19dd 361}
1bbd0b84 362#undef FUNC_NAME
0f2d19dd 363
3b3b36dd 364SCM_DEFINE (scm_list_set_x, "list-set!", 3, 0, 0,
1bbd0b84 365 (SCM lst, SCM k, SCM val),
b380b885 366 "Set the @var{k}th element of @var{lst} to @var{val}.")
1bbd0b84
GB
367#define FUNC_NAME s_scm_list_set_x
368{
369 register long i;
3b3b36dd 370 SCM_VALIDATE_INUM_MIN_COPY (2,k,0,i);
1bbd0b84 371 while (i-- > 0) {
0c95b57d 372 SCM_ASRTGO(SCM_CONSP(lst), erout);
1bbd0b84
GB
373 lst = SCM_CDR(lst);
374 }
375 erout:
0c95b57d 376 SCM_ASSERT(SCM_CONSP(lst),
1bbd0b84
GB
377 SCM_NULLP(lst)?k:lst, SCM_NULLP(lst)?SCM_OUTOFRANGE:SCM_ARG1, FUNC_NAME);
378 SCM_SETCAR (lst, val);
379 return val;
0f2d19dd 380}
1bbd0b84 381#undef FUNC_NAME
0f2d19dd
JB
382
383
1bbd0b84
GB
384SCM_REGISTER_PROC(s_list_cdr_ref, "list-cdr-ref", 2, 0, 0, scm_list_tail);
385
3b3b36dd 386SCM_DEFINE (scm_list_tail, "list-tail", 2, 0, 0,
1bbd0b84 387 (SCM lst, SCM k),
b380b885
MD
388 "Return the \"tail\" of @var{lst} beginning with its @var{k}th element.\n"
389 "The first element of the list is considered to be element 0.\n\n"
390 "@code{list-cdr-ref} and @code{list-tail} are identical. It may help to\n"
391 "think of @code{list-cdr-ref} as accessing the @var{k}th cdr of the list,\n"
392 "or returning the results of cdring @var{k} times down @var{lst}.")
1bbd0b84 393#define FUNC_NAME s_scm_list_tail
df13742c
JB
394{
395 register long i;
3b3b36dd 396 SCM_VALIDATE_INUM_MIN_COPY (2,k,0,i);
df13742c 397 while (i-- > 0) {
3b3b36dd 398 SCM_VALIDATE_CONS (1,lst);
df13742c
JB
399 lst = SCM_CDR(lst);
400 }
401 return lst;
402}
1bbd0b84 403#undef FUNC_NAME
df13742c 404
0f2d19dd 405
3b3b36dd 406SCM_DEFINE (scm_list_cdr_set_x, "list-cdr-set!", 3, 0, 0,
1bbd0b84 407 (SCM lst, SCM k, SCM val),
b380b885 408 "Set the @var{k}th cdr of @var{lst} to @var{val}.")
1bbd0b84
GB
409#define FUNC_NAME s_scm_list_cdr_set_x
410{
411 register long i;
3b3b36dd 412 SCM_VALIDATE_INUM_MIN_COPY (2,k,0,i);
1bbd0b84 413 while (i-- > 0) {
0c95b57d 414 SCM_ASRTGO(SCM_CONSP(lst), erout);
1bbd0b84
GB
415 lst = SCM_CDR(lst);
416 }
417erout:
0c95b57d 418 SCM_ASSERT(SCM_CONSP(lst),
1bbd0b84
GB
419 SCM_NULLP(lst)?k:lst, SCM_NULLP(lst)?SCM_OUTOFRANGE:SCM_ARG1, FUNC_NAME);
420 SCM_SETCDR (lst, val);
421 return val;
0f2d19dd 422}
1bbd0b84 423#undef FUNC_NAME
0f2d19dd
JB
424
425
426\f
df13742c 427/* copying lists, perhaps partially */
0f2d19dd 428
3b3b36dd 429SCM_DEFINE (scm_list_head, "list-head", 2, 0, 0,
1bbd0b84 430 (SCM lst, SCM k),
b380b885
MD
431 "Copy the first @var{k} elements from @var{lst} into a new list, and\n"
432 "return it.")
1bbd0b84 433#define FUNC_NAME s_scm_list_head
0f2d19dd
JB
434{
435 SCM answer;
436 SCM * pos;
437 register long i;
438
3b3b36dd 439 SCM_VALIDATE_INUM_MIN_COPY (2,k,0,i);
0f2d19dd
JB
440 answer = SCM_EOL;
441 pos = &answer;
0f2d19dd
JB
442 while (i-- > 0)
443 {
3b3b36dd 444 SCM_VALIDATE_CONS (1,lst);
0f2d19dd 445 *pos = scm_cons (SCM_CAR (lst), SCM_EOL);
25d8012c 446 pos = SCM_CDRLOC (*pos);
0f2d19dd
JB
447 lst = SCM_CDR(lst);
448 }
449 return answer;
450}
1bbd0b84 451#undef FUNC_NAME
0f2d19dd
JB
452
453
a1ec6916 454SCM_DEFINE (scm_list_copy, "list-copy", 1, 0, 0,
1bbd0b84 455 (SCM lst),
b380b885 456 "Return a (newly-created) copy of @var{lst}.")
1bbd0b84 457#define FUNC_NAME s_scm_list_copy
df13742c
JB
458{
459 SCM newlst;
460 SCM * fill_here;
461 SCM from_here;
462
463 newlst = SCM_EOL;
464 fill_here = &newlst;
465 from_here = lst;
466
0c95b57d 467 while (SCM_CONSP (from_here))
df13742c
JB
468 {
469 SCM c;
470 c = scm_cons (SCM_CAR (from_here), SCM_CDR (from_here));
471 *fill_here = c;
25d8012c 472 fill_here = SCM_CDRLOC (c);
df13742c
JB
473 from_here = SCM_CDR (from_here);
474 }
475 return newlst;
476}
1bbd0b84 477#undef FUNC_NAME
df13742c 478
0f2d19dd 479\f
df13742c
JB
480/* membership tests (memq, memv, etc.) */
481
a1ec6916 482SCM_DEFINE (scm_sloppy_memq, "sloppy-memq", 2, 0, 0,
1bbd0b84 483 (SCM x, SCM lst),
b450f070
GB
484 "This procedure behaves like @code{memq}, but does no type or error checking.\n"
485 "Its use is recommended only in writing Guile internals,\n"
486 "not for high-level Scheme programs.")
1bbd0b84 487#define FUNC_NAME s_scm_sloppy_memq
0f2d19dd 488{
0c95b57d 489 for(; SCM_CONSP (lst); lst = SCM_CDR(lst))
0f2d19dd 490 {
fbd485ba 491 if (SCM_EQ_P (SCM_CAR (lst), x))
0f2d19dd
JB
492 return lst;
493 }
494 return lst;
495}
1bbd0b84 496#undef FUNC_NAME
0f2d19dd
JB
497
498
a1ec6916 499SCM_DEFINE (scm_sloppy_memv, "sloppy-memv", 2, 0, 0,
1bbd0b84 500 (SCM x, SCM lst),
b450f070
GB
501 "This procedure behaves like @code{memv}, but does no type or error checking.\n"
502 "Its use is recommended only in writing Guile internals,\n"
503 "not for high-level Scheme programs.")
1bbd0b84 504#define FUNC_NAME s_scm_sloppy_memv
0f2d19dd 505{
0c95b57d 506 for(; SCM_CONSP (lst); lst = SCM_CDR(lst))
0f2d19dd 507 {
fbd485ba 508 if (! SCM_FALSEP (scm_eqv_p (SCM_CAR (lst), x)))
0f2d19dd
JB
509 return lst;
510 }
511 return lst;
512}
1bbd0b84 513#undef FUNC_NAME
0f2d19dd
JB
514
515
a1ec6916 516SCM_DEFINE (scm_sloppy_member, "sloppy-member", 2, 0, 0,
1bbd0b84 517 (SCM x, SCM lst),
b450f070
GB
518 "This procedure behaves like @code{member}, but does no type or error checking.\n"
519 "Its use is recommended only in writing Guile internals,\n"
520 "not for high-level Scheme programs.")
1bbd0b84 521#define FUNC_NAME s_scm_sloppy_member
0f2d19dd 522{
0c95b57d 523 for(; SCM_CONSP (lst); lst = SCM_CDR(lst))
0f2d19dd 524 {
fbd485ba 525 if (! SCM_FALSEP (scm_equal_p (SCM_CAR (lst), x)))
0f2d19dd
JB
526 return lst;
527 }
528 return lst;
529}
1bbd0b84 530#undef FUNC_NAME
0f2d19dd
JB
531
532
533
3b3b36dd 534SCM_DEFINE (scm_memq, "memq", 2, 0, 0,
1bbd0b84 535 (SCM x, SCM lst),
b450f070
GB
536 "Return the first sublist of LST whose car is `eq?' to X\n"
537 "where the sublists of LST are the non-empty lists returned\n"
538 "by `(list-tail LST K)' for K less than the length of LST. If\n"
539 "X does not occur in LST, then `#f' (not the empty list) is\n"
540 "returned.")
1bbd0b84 541#define FUNC_NAME s_scm_memq
0f2d19dd
JB
542{
543 SCM answer;
3b3b36dd 544 SCM_VALIDATE_LIST (2,lst);
0f2d19dd 545 answer = scm_sloppy_memq (x, lst);
fbd485ba 546 return (SCM_NULLP (answer)) ? SCM_BOOL_F : answer;
0f2d19dd 547}
1bbd0b84 548#undef FUNC_NAME
0f2d19dd
JB
549
550
551
3b3b36dd 552SCM_DEFINE (scm_memv, "memv", 2, 0, 0,
1bbd0b84 553 (SCM x, SCM lst),
b450f070
GB
554 "Return the first sublist of LST whose car is `eqv?' to X\n"
555 "where the sublists of LST are the non-empty lists returned\n"
556 "by `(list-tail LST K)' for K less than the length of LST. If\n"
557 "X does not occur in LST, then `#f' (not the empty list) is\n"
558 "returned.")
1bbd0b84 559#define FUNC_NAME s_scm_memv
0f2d19dd
JB
560{
561 SCM answer;
3b3b36dd 562 SCM_VALIDATE_LIST (2,lst);
0f2d19dd 563 answer = scm_sloppy_memv (x, lst);
fbd485ba 564 return (SCM_NULLP (answer)) ? SCM_BOOL_F : answer;
0f2d19dd 565}
1bbd0b84 566#undef FUNC_NAME
0f2d19dd
JB
567
568
3b3b36dd 569SCM_DEFINE (scm_member, "member", 2, 0, 0,
1bbd0b84 570 (SCM x, SCM lst),
b450f070
GB
571 "Return the first sublist of LST whose car is `equal?' to X\n"
572 "where the sublists of LST are the non-empty lists returned\n"
573 "by `(list-tail LST K)' for K less than the length of LST. If\n"
574 "X does not occur in LST, then `#f' (not the empty list) is\n"
575 "returned.")
1bbd0b84 576#define FUNC_NAME s_scm_member
0f2d19dd
JB
577{
578 SCM answer;
3b3b36dd 579 SCM_VALIDATE_LIST (2,lst);
0f2d19dd 580 answer = scm_sloppy_member (x, lst);
fbd485ba 581 return (SCM_NULLP (answer)) ? SCM_BOOL_F : answer;
0f2d19dd 582}
1bbd0b84 583#undef FUNC_NAME
0f2d19dd
JB
584
585
586\f
df13742c 587/* deleting elements from a list (delq, etc.) */
0f2d19dd 588
3b3b36dd 589SCM_DEFINE (scm_delq_x, "delq!", 2, 0, 0,
1bbd0b84 590 (SCM item, SCM lst),
b380b885
MD
591 "@deffnx primitive delv! item lst\n"
592 "@deffnx primitive delete! item lst\n"
593 "These procedures are destructive versions of @code{delq}, @code{delv}\n"
594 "and @code{delete}: they modify the pointers in the existing @var{lst}\n"
595 "rather than creating a new list. Caveat evaluator: Like other\n"
596 "destructive list functions, these functions cannot modify the binding of\n"
597 "@var{lst}, and so cannot be used to delete the first element of\n"
598 "@var{lst} destructively.")
1bbd0b84 599#define FUNC_NAME s_scm_delq_x
0f2d19dd 600{
164271a1
JB
601 SCM walk;
602 SCM *prev;
0f2d19dd 603
164271a1 604 for (prev = &lst, walk = lst;
0c95b57d 605 SCM_CONSP (walk);
164271a1 606 walk = SCM_CDR (walk))
0f2d19dd 607 {
fbd485ba 608 if (SCM_EQ_P (SCM_CAR (walk), item))
164271a1
JB
609 *prev = SCM_CDR (walk);
610 else
611 prev = SCM_CDRLOC (walk);
0f2d19dd 612 }
164271a1
JB
613
614 return lst;
0f2d19dd 615}
1bbd0b84 616#undef FUNC_NAME
0f2d19dd
JB
617
618
3b3b36dd 619SCM_DEFINE (scm_delv_x, "delv!", 2, 0, 0,
1bbd0b84 620 (SCM item, SCM lst),
b450f070 621 "Destructively remove all elements from LST that are `eqv?' to ITEM.")
1bbd0b84 622#define FUNC_NAME s_scm_delv_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_FALSEP (scm_eqv_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
642
3b3b36dd 643SCM_DEFINE (scm_delete_x, "delete!", 2, 0, 0,
1bbd0b84 644 (SCM item, SCM lst),
b450f070 645 "Destructively remove all elements from LST that are `equal?' to ITEM.")
1bbd0b84 646#define FUNC_NAME s_scm_delete_x
0f2d19dd 647{
164271a1
JB
648 SCM walk;
649 SCM *prev;
0f2d19dd 650
164271a1 651 for (prev = &lst, walk = lst;
0c95b57d 652 SCM_CONSP (walk);
164271a1 653 walk = SCM_CDR (walk))
0f2d19dd 654 {
fbd485ba 655 if (! SCM_FALSEP (scm_equal_p (SCM_CAR (walk), item)))
164271a1
JB
656 *prev = SCM_CDR (walk);
657 else
658 prev = SCM_CDRLOC (walk);
0f2d19dd 659 }
164271a1
JB
660
661 return lst;
0f2d19dd 662}
1bbd0b84 663#undef FUNC_NAME
0f2d19dd
JB
664
665
666\f
667
0f2d19dd 668
a1ec6916 669SCM_DEFINE (scm_delq, "delq", 2, 0, 0,
1bbd0b84 670 (SCM item, SCM lst),
b450f070
GB
671 "Return a newly-created copy of @var{lst} with elements `eq?' to @var{item} removed.\n"
672 "This procedure mirrors @code{memq}:\n"
b380b885 673 "@code{delq} compares elements of @var{lst} against @var{item} with\n"
b450f070 674 "@code{eq?}.")
1bbd0b84 675#define FUNC_NAME s_scm_delq
0f2d19dd 676{
1bbd0b84 677 SCM copy = scm_list_copy (lst);
0f2d19dd
JB
678 return scm_delq_x (item, copy);
679}
1bbd0b84 680#undef FUNC_NAME
0f2d19dd 681
a1ec6916 682SCM_DEFINE (scm_delv, "delv", 2, 0, 0,
1bbd0b84 683 (SCM item, SCM lst),
b450f070
GB
684 "Return a newly-created copy of @var{lst} with elements `eqv?' to @var{item} removed.\n"
685 "This procedure mirrors @code{memv}:\n"
686 "@code{delv} compares elements of @var{lst} against @var{item} with\n"
687 "@code{eqv?}.")
1bbd0b84 688#define FUNC_NAME s_scm_delv
0f2d19dd 689{
1bbd0b84 690 SCM copy = scm_list_copy (lst);
0f2d19dd
JB
691 return scm_delv_x (item, copy);
692}
1bbd0b84 693#undef FUNC_NAME
0f2d19dd 694
a1ec6916 695SCM_DEFINE (scm_delete, "delete", 2, 0, 0,
1bbd0b84 696 (SCM item, SCM lst),
b450f070
GB
697 "Return a newly-created copy of @var{lst} with elements `equal?' to @var{item} removed.\n"
698 "This procedure mirrors @code{member}:\n"
699 "@code{delete} compares elements of @var{lst} against @var{item} with\n"
700 "@code{equal?}.")
1bbd0b84 701#define FUNC_NAME s_scm_delete
0f2d19dd 702{
1bbd0b84 703 SCM copy = scm_list_copy (lst);
0f2d19dd
JB
704 return scm_delete_x (item, copy);
705}
1bbd0b84 706#undef FUNC_NAME
0f2d19dd
JB
707
708
3b3b36dd 709SCM_DEFINE (scm_delq1_x, "delq1!", 2, 0, 0,
1bbd0b84 710 (SCM item, SCM lst),
8507b88c
GB
711 "Like `delq!', but only deletes the first occurrence of ITEM from LST.\n"
712 "Tests for equality using `eq?'. See also `delv1!' and `delete1!'.")
1bbd0b84 713#define FUNC_NAME s_scm_delq1_x
82dc9f57
MD
714{
715 SCM walk;
716 SCM *prev;
717
718 for (prev = &lst, walk = lst;
0c95b57d 719 SCM_CONSP (walk);
82dc9f57
MD
720 walk = SCM_CDR (walk))
721 {
fbd485ba 722 if (SCM_EQ_P (SCM_CAR (walk), item))
82dc9f57
MD
723 {
724 *prev = SCM_CDR (walk);
725 break;
726 }
727 else
728 prev = SCM_CDRLOC (walk);
729 }
730
731 return lst;
732}
1bbd0b84 733#undef FUNC_NAME
82dc9f57
MD
734
735
3b3b36dd 736SCM_DEFINE (scm_delv1_x, "delv1!", 2, 0, 0,
8507b88c
GB
737 (SCM item, SCM lst),
738 "Like `delv!', but only deletes the first occurrence of ITEM from LST.\n"
739 "Tests for equality using `eqv?'. See also `delq1!' and `delete1!'.")
1bbd0b84 740#define FUNC_NAME s_scm_delv1_x
82dc9f57
MD
741{
742 SCM walk;
743 SCM *prev;
744
745 for (prev = &lst, walk = lst;
0c95b57d 746 SCM_CONSP (walk);
82dc9f57
MD
747 walk = SCM_CDR (walk))
748 {
fbd485ba 749 if (! SCM_FALSEP (scm_eqv_p (SCM_CAR (walk), item)))
82dc9f57
MD
750 {
751 *prev = SCM_CDR (walk);
752 break;
753 }
754 else
755 prev = SCM_CDRLOC (walk);
756 }
757
758 return lst;
759}
1bbd0b84 760#undef FUNC_NAME
82dc9f57
MD
761
762
3b3b36dd 763SCM_DEFINE (scm_delete1_x, "delete1!", 2, 0, 0,
8507b88c
GB
764 (SCM item, SCM lst),
765 "Like `delete!', but only deletes the first occurrence of ITEM from LST.\n"
766 "Tests for equality using `equal?'. See also `delq1!' and `delv1!'.")
1bbd0b84 767#define FUNC_NAME s_scm_delete1_x
82dc9f57
MD
768{
769 SCM walk;
770 SCM *prev;
771
772 for (prev = &lst, walk = lst;
0c95b57d 773 SCM_CONSP (walk);
82dc9f57
MD
774 walk = SCM_CDR (walk))
775 {
fbd485ba 776 if (! SCM_FALSEP (scm_equal_p (SCM_CAR (walk), item)))
82dc9f57
MD
777 {
778 *prev = SCM_CDR (walk);
779 break;
780 }
781 else
782 prev = SCM_CDRLOC (walk);
783 }
784
785 return lst;
786}
1bbd0b84 787#undef FUNC_NAME
82dc9f57
MD
788
789
0f2d19dd 790\f
0f2d19dd
JB
791void
792scm_init_list ()
0f2d19dd 793{
a0599745 794#include "libguile/list.x"
0f2d19dd 795}
89e00824
ML
796
797/*
798 Local Variables:
799 c-file-style: "gnu"
800 End:
801*/