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