*** empty log message ***
[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>
47#include "_scm.h"
20e6290e
JB
48#include "eq.h"
49
1bbd0b84 50#include "scm_validate.h"
20e6290e 51#include "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);
0f2d19dd
JB
72 while (elt != SCM_UNDEFINED)
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
GB
83 (SCM objs),
84"")
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
GB
116 (SCM x),
117"")
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
GB
126 (SCM x),
127"")
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 }
448a3bc2 158 while (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
GB
167 (SCM lst),
168"")
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),
fc0d72d4
MD
183 "A destructive version of @code{append} (@pxref{Pairs and Lists,,,r4rs,\n"
184 "The Revised^4 Report on Scheme}). The cdr field of each list's final\n"
185 "pair is changed to point to the head of the next list, so no consing is\n"
186 "performed. Return a pointer to the mutated list.")
1bbd0b84 187#define FUNC_NAME s_scm_append
0f2d19dd
JB
188{
189 SCM res = SCM_EOL;
190 SCM *lloc = &res, arg;
ff467021 191 if (SCM_IMP(args)) {
3b3b36dd 192 SCM_VALIDATE_NULL (SCM_ARGn, args);
0f2d19dd
JB
193 return res;
194 }
3b3b36dd 195 SCM_VALIDATE_CONS (SCM_ARGn, args);
0f2d19dd
JB
196 while (1) {
197 arg = SCM_CAR(args);
198 args = SCM_CDR(args);
ff467021 199 if (SCM_IMP(args)) {
0f2d19dd 200 *lloc = arg;
3b3b36dd 201 SCM_VALIDATE_NULL (SCM_ARGn, args);
0f2d19dd
JB
202 return res;
203 }
3b3b36dd 204 SCM_VALIDATE_CONS (SCM_ARGn, args);
e1385ffc 205 for (; SCM_CONSP(arg); arg = SCM_CDR(arg)) {
0f2d19dd 206 *lloc = scm_cons(SCM_CAR(arg), SCM_EOL);
25d8012c 207 lloc = SCM_CDRLOC(*lloc);
0f2d19dd 208 }
3b3b36dd 209 SCM_VALIDATE_NULL (SCM_ARGn, arg);
0f2d19dd
JB
210 }
211}
1bbd0b84 212#undef FUNC_NAME
0f2d19dd
JB
213
214
a1ec6916 215SCM_DEFINE (scm_append_x, "append!", 0, 0, 1,
1bbd0b84
GB
216 (SCM args),
217"")
218#define FUNC_NAME s_scm_append_x
0f2d19dd
JB
219{
220 SCM arg;
221 tail:
ff467021 222 if (SCM_NULLP(args)) return SCM_EOL;
0f2d19dd 223 arg = SCM_CAR(args);
0f2d19dd 224 args = SCM_CDR(args);
ff467021
JB
225 if (SCM_NULLP(args)) return arg;
226 if (SCM_NULLP(arg)) goto tail;
3b3b36dd 227 SCM_VALIDATE_CONS (SCM_ARG1,arg);
92396c0a 228 SCM_SETCDR (scm_last_pair (arg), scm_append_x (args));
0f2d19dd
JB
229 return arg;
230}
1bbd0b84 231#undef FUNC_NAME
0f2d19dd
JB
232
233
3b3b36dd 234SCM_DEFINE (scm_last_pair, "last-pair", 1, 0, 0,
e1385ffc 235 (SCM lst),
b380b885
MD
236 "Return a pointer to the last pair in @var{lst}, signalling an error if\n"
237 "@var{lst} is circular.")
1bbd0b84 238#define FUNC_NAME s_scm_last_pair
df13742c 239{
e1385ffc
GB
240 SCM tortoise = lst;
241 SCM hare = lst;
0f2d19dd 242
e1385ffc 243 if (SCM_NULLP (lst))
df13742c
JB
244 return SCM_EOL;
245
e1385ffc
GB
246 SCM_VALIDATE_CONS (SCM_ARG1, lst);
247 do {
248 SCM ahead = SCM_CDR(hare);
249 if (SCM_NCONSP(ahead)) return hare;
250 hare = ahead;
251 ahead = SCM_CDR(hare);
252 if (SCM_NCONSP(ahead)) return hare;
253 hare = ahead;
254 tortoise = SCM_CDR(tortoise);
df13742c 255 }
e1385ffc 256 while (hare != tortoise);
5d2d2ffc 257 SCM_MISC_ERROR ("Circular structure in position 1: ~S", SCM_LIST1 (lst));
df13742c 258}
1bbd0b84 259#undef FUNC_NAME
df13742c
JB
260
261\f
262/* reversing lists */
0f2d19dd 263
a1ec6916 264SCM_DEFINE (scm_reverse, "reverse", 1, 0, 0,
e1385ffc 265 (SCM lst),
b380b885 266 "")
e1385ffc
GB
267#define FUNC_NAME s_scm_reverse
268{
269 SCM result = SCM_EOL;
270 SCM tortoise = lst;
271 SCM hare = lst;
272
273 do {
274 if (SCM_NULLP(hare)) return result;
275 SCM_ASSERT(SCM_CONSP(hare), lst, 1, FUNC_NAME);
276 result = scm_cons (SCM_CAR (hare), result);
277 hare = SCM_CDR (hare);
278 if (SCM_NULLP(hare)) return result;
279 SCM_ASSERT(SCM_CONSP(hare), lst, 1, FUNC_NAME);
280 result = scm_cons (SCM_CAR (hare), result);
281 hare = SCM_CDR (hare);
282 tortoise = SCM_CDR (tortoise);
283 }
284 while (hare != tortoise);
5d2d2ffc 285 SCM_MISC_ERROR ("Circular structure in position 1: ~S", SCM_LIST1 (lst));
e1385ffc
GB
286}
287#undef FUNC_NAME
288
289SCM_DEFINE (scm_reverse_x, "reverse!", 1, 1, 0,
290 (SCM lst, SCM new_tail),
b380b885
MD
291 "A destructive version of @code{reverse} (@pxref{Pairs and Lists,,,r4rs,\n"
292 "The Revised^4 Report on Scheme}). The cdr of each cell in @var{lst} is\n"
293 "modified to point to the previous list element. Return a pointer to the\n"
294 "head of the reversed list.\n\n"
295 "Caveat: because the list is modified in place, the tail of the original\n"
296 "list now becomes its head, and the head of the original list now becomes\n"
297 "the tail. Therefore, the @var{lst} symbol to which the head of the\n"
298 "original list was bound now points to the tail. To ensure that the head\n"
299 "of the modified list is not lost, it is wise to save the return value of\n"
300 "@code{reverse!}")
1bbd0b84 301#define FUNC_NAME s_scm_reverse_x
0f2d19dd 302{
e1385ffc 303 SCM_ASSERT (scm_ilength (lst) >= 0, lst, SCM_ARG1, FUNC_NAME);
3946f0de
MD
304 if (SCM_UNBNDP (new_tail))
305 new_tail = SCM_EOL;
306 else
1bbd0b84 307 SCM_ASSERT (scm_ilength (new_tail) >= 0, new_tail, SCM_ARG2, FUNC_NAME);
0f2d19dd 308
e1385ffc 309 while (SCM_NNULLP (lst))
3946f0de 310 {
e1385ffc
GB
311 SCM old_tail = SCM_CDR (lst);
312 SCM_SETCDR (lst, new_tail);
313 new_tail = lst;
314 lst = old_tail;
3946f0de
MD
315 }
316 return new_tail;
0f2d19dd 317}
1bbd0b84 318#undef FUNC_NAME
0f2d19dd
JB
319
320
321\f
df13742c 322/* indexing lists by element number */
0f2d19dd 323
3b3b36dd 324SCM_DEFINE (scm_list_ref, "list-ref", 2, 0, 0,
1bbd0b84 325 (SCM lst, SCM k),
b380b885 326 "")
1bbd0b84
GB
327#define FUNC_NAME s_scm_list_ref
328{
329 register long i;
3b3b36dd 330 SCM_VALIDATE_INUM_MIN_COPY (2,k,0,i);
1bbd0b84 331 while (i-- > 0) {
0c95b57d 332 SCM_ASRTGO(SCM_CONSP(lst), erout);
1bbd0b84
GB
333 lst = SCM_CDR(lst);
334 }
335 erout:
0c95b57d 336 SCM_ASSERT(SCM_CONSP(lst),
1bbd0b84
GB
337 SCM_NULLP(lst)?k:lst, SCM_NULLP(lst)?SCM_OUTOFRANGE:SCM_ARG1, FUNC_NAME);
338 return SCM_CAR(lst);
0f2d19dd 339}
1bbd0b84 340#undef FUNC_NAME
0f2d19dd 341
3b3b36dd 342SCM_DEFINE (scm_list_set_x, "list-set!", 3, 0, 0,
1bbd0b84 343 (SCM lst, SCM k, SCM val),
b380b885 344 "Set the @var{k}th element of @var{lst} to @var{val}.")
1bbd0b84
GB
345#define FUNC_NAME s_scm_list_set_x
346{
347 register long i;
3b3b36dd 348 SCM_VALIDATE_INUM_MIN_COPY (2,k,0,i);
1bbd0b84 349 while (i-- > 0) {
0c95b57d 350 SCM_ASRTGO(SCM_CONSP(lst), erout);
1bbd0b84
GB
351 lst = SCM_CDR(lst);
352 }
353 erout:
0c95b57d 354 SCM_ASSERT(SCM_CONSP(lst),
1bbd0b84
GB
355 SCM_NULLP(lst)?k:lst, SCM_NULLP(lst)?SCM_OUTOFRANGE:SCM_ARG1, FUNC_NAME);
356 SCM_SETCAR (lst, val);
357 return val;
0f2d19dd 358}
1bbd0b84 359#undef FUNC_NAME
0f2d19dd
JB
360
361
1bbd0b84
GB
362SCM_REGISTER_PROC(s_list_cdr_ref, "list-cdr-ref", 2, 0, 0, scm_list_tail);
363
3b3b36dd 364SCM_DEFINE (scm_list_tail, "list-tail", 2, 0, 0,
1bbd0b84 365 (SCM lst, SCM k),
b380b885
MD
366 "Return the \"tail\" of @var{lst} beginning with its @var{k}th element.\n"
367 "The first element of the list is considered to be element 0.\n\n"
368 "@code{list-cdr-ref} and @code{list-tail} are identical. It may help to\n"
369 "think of @code{list-cdr-ref} as accessing the @var{k}th cdr of the list,\n"
370 "or returning the results of cdring @var{k} times down @var{lst}.")
1bbd0b84 371#define FUNC_NAME s_scm_list_tail
df13742c
JB
372{
373 register long i;
3b3b36dd 374 SCM_VALIDATE_INUM_MIN_COPY (2,k,0,i);
df13742c 375 while (i-- > 0) {
3b3b36dd 376 SCM_VALIDATE_CONS (1,lst);
df13742c
JB
377 lst = SCM_CDR(lst);
378 }
379 return lst;
380}
1bbd0b84 381#undef FUNC_NAME
df13742c 382
0f2d19dd 383
3b3b36dd 384SCM_DEFINE (scm_list_cdr_set_x, "list-cdr-set!", 3, 0, 0,
1bbd0b84 385 (SCM lst, SCM k, SCM val),
b380b885 386 "Set the @var{k}th cdr of @var{lst} to @var{val}.")
1bbd0b84
GB
387#define FUNC_NAME s_scm_list_cdr_set_x
388{
389 register long i;
3b3b36dd 390 SCM_VALIDATE_INUM_MIN_COPY (2,k,0,i);
1bbd0b84 391 while (i-- > 0) {
0c95b57d 392 SCM_ASRTGO(SCM_CONSP(lst), erout);
1bbd0b84
GB
393 lst = SCM_CDR(lst);
394 }
395erout:
0c95b57d 396 SCM_ASSERT(SCM_CONSP(lst),
1bbd0b84
GB
397 SCM_NULLP(lst)?k:lst, SCM_NULLP(lst)?SCM_OUTOFRANGE:SCM_ARG1, FUNC_NAME);
398 SCM_SETCDR (lst, val);
399 return val;
0f2d19dd 400}
1bbd0b84 401#undef FUNC_NAME
0f2d19dd
JB
402
403
404\f
df13742c 405/* copying lists, perhaps partially */
0f2d19dd 406
3b3b36dd 407SCM_DEFINE (scm_list_head, "list-head", 2, 0, 0,
1bbd0b84 408 (SCM lst, SCM k),
b380b885
MD
409 "Copy the first @var{k} elements from @var{lst} into a new list, and\n"
410 "return it.")
1bbd0b84 411#define FUNC_NAME s_scm_list_head
0f2d19dd
JB
412{
413 SCM answer;
414 SCM * pos;
415 register long i;
416
3b3b36dd 417 SCM_VALIDATE_INUM_MIN_COPY (2,k,0,i);
0f2d19dd
JB
418 answer = SCM_EOL;
419 pos = &answer;
0f2d19dd
JB
420 while (i-- > 0)
421 {
3b3b36dd 422 SCM_VALIDATE_CONS (1,lst);
0f2d19dd 423 *pos = scm_cons (SCM_CAR (lst), SCM_EOL);
25d8012c 424 pos = SCM_CDRLOC (*pos);
0f2d19dd
JB
425 lst = SCM_CDR(lst);
426 }
427 return answer;
428}
1bbd0b84 429#undef FUNC_NAME
0f2d19dd
JB
430
431
a1ec6916 432SCM_DEFINE (scm_list_copy, "list-copy", 1, 0, 0,
1bbd0b84 433 (SCM lst),
b380b885 434 "Return a (newly-created) copy of @var{lst}.")
1bbd0b84 435#define FUNC_NAME s_scm_list_copy
df13742c
JB
436{
437 SCM newlst;
438 SCM * fill_here;
439 SCM from_here;
440
441 newlst = SCM_EOL;
442 fill_here = &newlst;
443 from_here = lst;
444
0c95b57d 445 while (SCM_CONSP (from_here))
df13742c
JB
446 {
447 SCM c;
448 c = scm_cons (SCM_CAR (from_here), SCM_CDR (from_here));
449 *fill_here = c;
25d8012c 450 fill_here = SCM_CDRLOC (c);
df13742c
JB
451 from_here = SCM_CDR (from_here);
452 }
453 return newlst;
454}
1bbd0b84 455#undef FUNC_NAME
df13742c 456
0f2d19dd 457\f
df13742c
JB
458/* membership tests (memq, memv, etc.) */
459
a1ec6916 460SCM_DEFINE (scm_sloppy_memq, "sloppy-memq", 2, 0, 0,
1bbd0b84 461 (SCM x, SCM lst),
b380b885
MD
462 "@deffnx primitive sloppy-memv\n"
463 "@deffnx primitive sloppy-member\n"
464 "These procedures behave like @code{memq}, @code{memv} and @code{member}\n"
465 "(@pxref{Pairs and Lists,,,r4rs, The Revised^4 Report on Scheme}), but do\n"
466 "not perform any type or error checking. Their use is recommended only\n"
467 "in writing Guile internals, not for high-level Scheme programs.")
1bbd0b84 468#define FUNC_NAME s_scm_sloppy_memq
0f2d19dd 469{
0c95b57d 470 for(; SCM_CONSP (lst); lst = SCM_CDR(lst))
0f2d19dd
JB
471 {
472 if (SCM_CAR(lst)==x)
473 return lst;
474 }
475 return lst;
476}
1bbd0b84 477#undef FUNC_NAME
0f2d19dd
JB
478
479
a1ec6916 480SCM_DEFINE (scm_sloppy_memv, "sloppy-memv", 2, 0, 0,
1bbd0b84 481 (SCM x, SCM lst),
b380b885 482 "")
1bbd0b84 483#define FUNC_NAME s_scm_sloppy_memv
0f2d19dd 484{
0c95b57d 485 for(; SCM_CONSP (lst); lst = SCM_CDR(lst))
0f2d19dd
JB
486 {
487 if (SCM_BOOL_F != scm_eqv_p (SCM_CAR(lst), x))
488 return lst;
489 }
490 return lst;
491}
1bbd0b84 492#undef FUNC_NAME
0f2d19dd
JB
493
494
a1ec6916 495SCM_DEFINE (scm_sloppy_member, "sloppy-member", 2, 0, 0,
1bbd0b84 496 (SCM x, SCM lst),
b380b885 497 "")
1bbd0b84 498#define FUNC_NAME s_scm_sloppy_member
0f2d19dd 499{
0c95b57d 500 for(; SCM_CONSP (lst); lst = SCM_CDR(lst))
0f2d19dd
JB
501 {
502 if (SCM_BOOL_F != scm_equal_p (SCM_CAR(lst), x))
503 return lst;
504 }
505 return lst;
506}
1bbd0b84 507#undef FUNC_NAME
0f2d19dd
JB
508
509
510
3b3b36dd 511SCM_DEFINE (scm_memq, "memq", 2, 0, 0,
1bbd0b84 512 (SCM x, SCM lst),
b380b885 513 "")
1bbd0b84 514#define FUNC_NAME s_scm_memq
0f2d19dd
JB
515{
516 SCM answer;
3b3b36dd 517 SCM_VALIDATE_LIST (2,lst);
0f2d19dd 518 answer = scm_sloppy_memq (x, lst);
df13742c 519 return (answer == SCM_EOL) ? SCM_BOOL_F : answer;
0f2d19dd 520}
1bbd0b84 521#undef FUNC_NAME
0f2d19dd
JB
522
523
524
3b3b36dd 525SCM_DEFINE (scm_memv, "memv", 2, 0, 0,
1bbd0b84 526 (SCM x, SCM lst),
b380b885 527 "")
1bbd0b84 528#define FUNC_NAME s_scm_memv
0f2d19dd
JB
529{
530 SCM answer;
3b3b36dd 531 SCM_VALIDATE_LIST (2,lst);
0f2d19dd 532 answer = scm_sloppy_memv (x, lst);
df13742c 533 return (answer == SCM_EOL) ? SCM_BOOL_F : answer;
0f2d19dd 534}
1bbd0b84 535#undef FUNC_NAME
0f2d19dd
JB
536
537
3b3b36dd 538SCM_DEFINE (scm_member, "member", 2, 0, 0,
1bbd0b84 539 (SCM x, SCM lst),
b380b885 540 "")
1bbd0b84 541#define FUNC_NAME s_scm_member
0f2d19dd
JB
542{
543 SCM answer;
3b3b36dd 544 SCM_VALIDATE_LIST (2,lst);
0f2d19dd 545 answer = scm_sloppy_member (x, lst);
df13742c 546 return (answer == SCM_EOL) ? SCM_BOOL_F : answer;
0f2d19dd 547}
1bbd0b84 548#undef FUNC_NAME
0f2d19dd
JB
549
550
551\f
df13742c 552/* deleting elements from a list (delq, etc.) */
0f2d19dd 553
3b3b36dd 554SCM_DEFINE (scm_delq_x, "delq!", 2, 0, 0,
1bbd0b84 555 (SCM item, SCM lst),
b380b885
MD
556 "@deffnx primitive delv! item lst\n"
557 "@deffnx primitive delete! item lst\n"
558 "These procedures are destructive versions of @code{delq}, @code{delv}\n"
559 "and @code{delete}: they modify the pointers in the existing @var{lst}\n"
560 "rather than creating a new list. Caveat evaluator: Like other\n"
561 "destructive list functions, these functions cannot modify the binding of\n"
562 "@var{lst}, and so cannot be used to delete the first element of\n"
563 "@var{lst} destructively.")
1bbd0b84 564#define FUNC_NAME s_scm_delq_x
0f2d19dd 565{
164271a1
JB
566 SCM walk;
567 SCM *prev;
0f2d19dd 568
164271a1 569 for (prev = &lst, walk = lst;
0c95b57d 570 SCM_CONSP (walk);
164271a1 571 walk = SCM_CDR (walk))
0f2d19dd 572 {
164271a1
JB
573 if (SCM_CAR (walk) == item)
574 *prev = SCM_CDR (walk);
575 else
576 prev = SCM_CDRLOC (walk);
0f2d19dd 577 }
164271a1
JB
578
579 return lst;
0f2d19dd 580}
1bbd0b84 581#undef FUNC_NAME
0f2d19dd
JB
582
583
3b3b36dd 584SCM_DEFINE (scm_delv_x, "delv!", 2, 0, 0,
1bbd0b84 585 (SCM item, SCM lst),
b380b885 586 "")
1bbd0b84 587#define FUNC_NAME s_scm_delv_x
0f2d19dd 588{
164271a1
JB
589 SCM walk;
590 SCM *prev;
0f2d19dd 591
164271a1 592 for (prev = &lst, walk = lst;
0c95b57d 593 SCM_CONSP (walk);
164271a1 594 walk = SCM_CDR (walk))
0f2d19dd 595 {
164271a1
JB
596 if (SCM_BOOL_F != scm_eqv_p (SCM_CAR (walk), item))
597 *prev = SCM_CDR (walk);
598 else
599 prev = SCM_CDRLOC (walk);
0f2d19dd 600 }
164271a1
JB
601
602 return lst;
0f2d19dd 603}
1bbd0b84 604#undef FUNC_NAME
0f2d19dd
JB
605
606
607
3b3b36dd 608SCM_DEFINE (scm_delete_x, "delete!", 2, 0, 0,
1bbd0b84 609 (SCM item, SCM lst),
b380b885 610 "")
1bbd0b84 611#define FUNC_NAME s_scm_delete_x
0f2d19dd 612{
164271a1
JB
613 SCM walk;
614 SCM *prev;
0f2d19dd 615
164271a1 616 for (prev = &lst, walk = lst;
0c95b57d 617 SCM_CONSP (walk);
164271a1 618 walk = SCM_CDR (walk))
0f2d19dd 619 {
164271a1
JB
620 if (SCM_BOOL_F != scm_equal_p (SCM_CAR (walk), item))
621 *prev = SCM_CDR (walk);
622 else
623 prev = SCM_CDRLOC (walk);
0f2d19dd 624 }
164271a1
JB
625
626 return lst;
0f2d19dd 627}
1bbd0b84 628#undef FUNC_NAME
0f2d19dd
JB
629
630
631\f
632
0f2d19dd 633
a1ec6916 634SCM_DEFINE (scm_delq, "delq", 2, 0, 0,
1bbd0b84 635 (SCM item, SCM lst),
b380b885
MD
636 "@deffnx primitive delv item lst\n"
637 "@deffnx primitive delete item lst\n"
638 "Return a newly-created copy of @var{lst} with @var{item} removed. These\n"
639 "procedures mirror @code{memq}, @code{memv} and @code{member}:\n"
640 "@code{delq} compares elements of @var{lst} against @var{item} with\n"
641 "@code{eq?}, @code{delv} uses @code{eqv?} and @code{delete} uses @code{equal?}")
1bbd0b84 642#define FUNC_NAME s_scm_delq
0f2d19dd 643{
1bbd0b84 644 SCM copy = scm_list_copy (lst);
0f2d19dd
JB
645 return scm_delq_x (item, copy);
646}
1bbd0b84 647#undef FUNC_NAME
0f2d19dd 648
a1ec6916 649SCM_DEFINE (scm_delv, "delv", 2, 0, 0,
1bbd0b84 650 (SCM item, SCM lst),
b380b885 651 "")
1bbd0b84 652#define FUNC_NAME s_scm_delv
0f2d19dd 653{
1bbd0b84 654 SCM copy = scm_list_copy (lst);
0f2d19dd
JB
655 return scm_delv_x (item, copy);
656}
1bbd0b84 657#undef FUNC_NAME
0f2d19dd 658
a1ec6916 659SCM_DEFINE (scm_delete, "delete", 2, 0, 0,
1bbd0b84 660 (SCM item, SCM lst),
b380b885 661 "")
1bbd0b84 662#define FUNC_NAME s_scm_delete
0f2d19dd 663{
1bbd0b84 664 SCM copy = scm_list_copy (lst);
0f2d19dd
JB
665 return scm_delete_x (item, copy);
666}
1bbd0b84 667#undef FUNC_NAME
0f2d19dd
JB
668
669
3b3b36dd 670SCM_DEFINE (scm_delq1_x, "delq1!", 2, 0, 0,
1bbd0b84 671 (SCM item, SCM lst),
b380b885 672 "")
1bbd0b84 673#define FUNC_NAME s_scm_delq1_x
82dc9f57
MD
674{
675 SCM walk;
676 SCM *prev;
677
678 for (prev = &lst, walk = lst;
0c95b57d 679 SCM_CONSP (walk);
82dc9f57
MD
680 walk = SCM_CDR (walk))
681 {
682 if (SCM_CAR (walk) == item)
683 {
684 *prev = SCM_CDR (walk);
685 break;
686 }
687 else
688 prev = SCM_CDRLOC (walk);
689 }
690
691 return lst;
692}
1bbd0b84 693#undef FUNC_NAME
82dc9f57
MD
694
695
3b3b36dd 696SCM_DEFINE (scm_delv1_x, "delv1!", 2, 0, 0,
1bbd0b84 697 (SCM item, SCM lst),
b380b885 698 "")
1bbd0b84 699#define FUNC_NAME s_scm_delv1_x
82dc9f57
MD
700{
701 SCM walk;
702 SCM *prev;
703
704 for (prev = &lst, walk = lst;
0c95b57d 705 SCM_CONSP (walk);
82dc9f57
MD
706 walk = SCM_CDR (walk))
707 {
708 if (SCM_BOOL_F != scm_eqv_p (SCM_CAR (walk), item))
709 {
710 *prev = SCM_CDR (walk);
711 break;
712 }
713 else
714 prev = SCM_CDRLOC (walk);
715 }
716
717 return lst;
718}
1bbd0b84 719#undef FUNC_NAME
82dc9f57
MD
720
721
3b3b36dd 722SCM_DEFINE (scm_delete1_x, "delete1!", 2, 0, 0,
1bbd0b84 723 (SCM item, SCM lst),
b380b885 724 "")
1bbd0b84 725#define FUNC_NAME s_scm_delete1_x
82dc9f57
MD
726{
727 SCM walk;
728 SCM *prev;
729
730 for (prev = &lst, walk = lst;
0c95b57d 731 SCM_CONSP (walk);
82dc9f57
MD
732 walk = SCM_CDR (walk))
733 {
734 if (SCM_BOOL_F != scm_equal_p (SCM_CAR (walk), item))
735 {
736 *prev = SCM_CDR (walk);
737 break;
738 }
739 else
740 prev = SCM_CDRLOC (walk);
741 }
742
743 return lst;
744}
1bbd0b84 745#undef FUNC_NAME
82dc9f57
MD
746
747
0f2d19dd 748\f
0f2d19dd
JB
749void
750scm_init_list ()
0f2d19dd
JB
751{
752#include "list.x"
753}