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