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