SRFI-1: Rewrite `alist-copy' in Scheme.
[bpt/guile.git] / libguile / srfi-1.c
1 /* srfi-1.c --- SRFI-1 procedures for Guile
2 *
3 * Copyright (C) 1995, 1996, 1997, 2000, 2001, 2002, 2003, 2005, 2006, 2008, 2009, 2010
4 * Free Software Foundation, Inc.
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public License
8 * as published by the Free Software Foundation; either version 3 of
9 * the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 * 02110-1301 USA
20 */
21
22 \f
23 #ifdef HAVE_CONFIG_H
24 # include <config.h>
25 #endif
26
27 #include "libguile/_scm.h"
28 #include "libguile/eq.h"
29
30 #include "libguile/validate.h"
31 #include "libguile/list.h"
32 #include "libguile/eval.h"
33 #include "libguile/srfi-1.h"
34
35 #include <stdarg.h>
36
37
38 /* The intent of this file was to gradually replace those Scheme
39 * procedures in srfi-1.scm that extend core primitive procedures,
40 * so that using srfi-1 wouldn't have performance penalties.
41 *
42 * However, we now prefer to write these procedures in Scheme, let the compiler
43 * optimize them, and have the VM execute them efficiently.
44 */
45
46
47 static long
48 srfi1_ilength (SCM sx)
49 {
50 long i = 0;
51 SCM tortoise = sx;
52 SCM hare = sx;
53
54 do {
55 if (SCM_NULL_OR_NIL_P(hare)) return i;
56 if (!scm_is_pair (hare)) return -2;
57 hare = SCM_CDR(hare);
58 i++;
59 if (SCM_NULL_OR_NIL_P(hare)) return i;
60 if (!scm_is_pair (hare)) return -2;
61 hare = SCM_CDR(hare);
62 i++;
63 /* For every two steps the hare takes, the tortoise takes one. */
64 tortoise = SCM_CDR(tortoise);
65 }
66 while (! scm_is_eq (hare, tortoise));
67
68 /* If the tortoise ever catches the hare, then the list must contain
69 a cycle. */
70 return -1;
71 }
72
73 static SCM
74 equal_trampoline (SCM proc, SCM arg1, SCM arg2)
75 {
76 return scm_equal_p (arg1, arg2);
77 }
78
79 /* list_copy_part() copies the first COUNT cells of LST, puts the result at
80 *dst, and returns the SCM_CDRLOC of the last cell in that new list.
81
82 This function is designed to be careful about LST possibly having changed
83 in between the caller deciding what to copy, and the copy actually being
84 done here. The COUNT ensures we terminate if LST has become circular,
85 SCM_VALIDATE_CONS guards against a cdr in the list changed to some
86 non-pair object. */
87
88 #include <stdio.h>
89 static SCM *
90 list_copy_part (SCM lst, int count, SCM *dst)
91 #define FUNC_NAME "list_copy_part"
92 {
93 SCM c;
94 for ( ; count > 0; count--)
95 {
96 SCM_VALIDATE_CONS (SCM_ARGn, lst);
97 c = scm_cons (SCM_CAR (lst), SCM_EOL);
98 *dst = c;
99 dst = SCM_CDRLOC (c);
100 lst = SCM_CDR (lst);
101 }
102 return dst;
103 }
104 #undef FUNC_NAME
105
106
107 SCM_DEFINE (scm_srfi1_append_reverse, "append-reverse", 2, 0, 0,
108 (SCM revhead, SCM tail),
109 "Reverse @var{rev-head}, append @var{tail} to it, and return the\n"
110 "result. This is equivalent to @code{(append (reverse\n"
111 "@var{rev-head}) @var{tail})}, but its implementation is more\n"
112 "efficient.\n"
113 "\n"
114 "@example\n"
115 "(append-reverse '(1 2 3) '(4 5 6)) @result{} (3 2 1 4 5 6)\n"
116 "@end example")
117 #define FUNC_NAME s_scm_srfi1_append_reverse
118 {
119 while (scm_is_pair (revhead))
120 {
121 /* copy first element of revhead onto front of tail */
122 tail = scm_cons (SCM_CAR (revhead), tail);
123 revhead = SCM_CDR (revhead);
124 }
125 SCM_ASSERT_TYPE (SCM_NULL_OR_NIL_P (revhead), revhead, SCM_ARG1, FUNC_NAME,
126 "list");
127 return tail;
128 }
129 #undef FUNC_NAME
130
131
132 SCM_DEFINE (scm_srfi1_append_reverse_x, "append-reverse!", 2, 0, 0,
133 (SCM revhead, SCM tail),
134 "Reverse @var{rev-head}, append @var{tail} to it, and return the\n"
135 "result. This is equivalent to @code{(append! (reverse!\n"
136 "@var{rev-head}) @var{tail})}, but its implementation is more\n"
137 "efficient.\n"
138 "\n"
139 "@example\n"
140 "(append-reverse! (list 1 2 3) '(4 5 6)) @result{} (3 2 1 4 5 6)\n"
141 "@end example\n"
142 "\n"
143 "@var{rev-head} may be modified in order to produce the result.")
144 #define FUNC_NAME s_scm_srfi1_append_reverse_x
145 {
146 SCM newtail;
147
148 while (scm_is_pair (revhead))
149 {
150 /* take the first cons cell from revhead */
151 newtail = revhead;
152 revhead = SCM_CDR (revhead);
153
154 /* make it the new start of tail, appending the previous */
155 SCM_SETCDR (newtail, tail);
156 tail = newtail;
157 }
158 SCM_ASSERT_TYPE (SCM_NULL_OR_NIL_P (revhead), revhead, SCM_ARG1, FUNC_NAME,
159 "list");
160 return tail;
161 }
162 #undef FUNC_NAME
163
164 SCM_DEFINE (scm_srfi1_concatenate, "concatenate", 1, 0, 0,
165 (SCM lstlst),
166 "Construct a list by appending all lists in @var{lstlst}.\n"
167 "\n"
168 "@code{concatenate} is the same as @code{(apply append\n"
169 "@var{lstlst})}. It exists because some Scheme implementations\n"
170 "have a limit on the number of arguments a function takes, which\n"
171 "the @code{apply} might exceed. In Guile there is no such\n"
172 "limit.")
173 #define FUNC_NAME s_scm_srfi1_concatenate
174 {
175 SCM_VALIDATE_LIST (SCM_ARG1, lstlst);
176 return scm_append (lstlst);
177 }
178 #undef FUNC_NAME
179
180
181 SCM_DEFINE (scm_srfi1_concatenate_x, "concatenate!", 1, 0, 0,
182 (SCM lstlst),
183 "Construct a list by appending all lists in @var{lstlst}. Those\n"
184 "lists may be modified to produce the result.\n"
185 "\n"
186 "@code{concatenate!} is the same as @code{(apply append!\n"
187 "@var{lstlst})}. It exists because some Scheme implementations\n"
188 "have a limit on the number of arguments a function takes, which\n"
189 "the @code{apply} might exceed. In Guile there is no such\n"
190 "limit.")
191 #define FUNC_NAME s_scm_srfi1_concatenate
192 {
193 SCM_VALIDATE_LIST (SCM_ARG1, lstlst);
194 return scm_append_x (lstlst);
195 }
196 #undef FUNC_NAME
197
198
199 SCM_DEFINE (scm_srfi1_count, "count", 2, 0, 1,
200 (SCM pred, SCM list1, SCM rest),
201 "Return a count of the number of times @var{pred} returns true\n"
202 "when called on elements from the given lists.\n"
203 "\n"
204 "@var{pred} is called with @var{N} parameters @code{(@var{pred}\n"
205 "@var{elem1} @dots{} @var{elemN})}, each element being from the\n"
206 "corresponding @var{list1} @dots{} @var{lstN}. The first call is\n"
207 "with the first element of each list, the second with the second\n"
208 "element from each, and so on.\n"
209 "\n"
210 "Counting stops when the end of the shortest list is reached.\n"
211 "At least one list must be non-circular.")
212 #define FUNC_NAME s_scm_srfi1_count
213 {
214 long count;
215 SCM lst;
216 int argnum;
217 SCM_VALIDATE_REST_ARGUMENT (rest);
218
219 count = 0;
220
221 if (scm_is_null (rest))
222 {
223 /* one list */
224 SCM_ASSERT (scm_is_true (scm_procedure_p (pred)), pred, SCM_ARG1, FUNC_NAME);
225
226 for ( ; scm_is_pair (list1); list1 = SCM_CDR (list1))
227 count += scm_is_true (scm_call_1 (pred, SCM_CAR (list1)));
228
229 /* check below that list1 is a proper list, and done */
230 end_list1:
231 lst = list1;
232 argnum = 2;
233 }
234 else if (scm_is_pair (rest) && scm_is_null (SCM_CDR (rest)))
235 {
236 /* two lists */
237 SCM list2;
238
239 SCM_ASSERT (scm_is_true (scm_procedure_p (pred)), pred, SCM_ARG1, FUNC_NAME);
240
241 list2 = SCM_CAR (rest);
242 for (;;)
243 {
244 if (! scm_is_pair (list1))
245 goto end_list1;
246 if (! scm_is_pair (list2))
247 {
248 lst = list2;
249 argnum = 3;
250 break;
251 }
252 count += scm_is_true (scm_call_2
253 (pred, SCM_CAR (list1), SCM_CAR (list2)));
254 list1 = SCM_CDR (list1);
255 list2 = SCM_CDR (list2);
256 }
257 }
258 else
259 {
260 /* three or more lists */
261 SCM vec, args, a;
262 size_t len, i;
263
264 /* vec is the list arguments */
265 vec = scm_vector (scm_cons (list1, rest));
266 len = SCM_SIMPLE_VECTOR_LENGTH (vec);
267
268 /* args is the argument list to pass to pred, same length as vec,
269 re-used for each call */
270 args = scm_make_list (SCM_I_MAKINUM (len), SCM_UNDEFINED);
271
272 for (;;)
273 {
274 /* first elem of each list in vec into args, and step those
275 vec entries onto their next element */
276 for (i = 0, a = args, argnum = 2;
277 i < len;
278 i++, a = SCM_CDR (a), argnum++)
279 {
280 lst = SCM_SIMPLE_VECTOR_REF (vec, i); /* list argument */
281 if (! scm_is_pair (lst))
282 goto check_lst_and_done;
283 SCM_SETCAR (a, SCM_CAR (lst)); /* arg for pred */
284 SCM_SIMPLE_VECTOR_SET (vec, i, SCM_CDR (lst)); /* rest of lst */
285 }
286
287 count += scm_is_true (scm_apply (pred, args, SCM_EOL));
288 }
289 }
290
291 check_lst_and_done:
292 SCM_ASSERT_TYPE (SCM_NULL_OR_NIL_P (lst), lst, argnum, FUNC_NAME, "list");
293 return scm_from_long (count);
294 }
295 #undef FUNC_NAME
296
297
298 SCM_DEFINE (scm_srfi1_delete, "delete", 2, 1, 0,
299 (SCM x, SCM lst, SCM pred),
300 "Return a list containing the elements of @var{lst} but with\n"
301 "those equal to @var{x} deleted. The returned elements will be\n"
302 "in the same order as they were in @var{lst}.\n"
303 "\n"
304 "Equality is determined by @var{pred}, or @code{equal?} if not\n"
305 "given. An equality call is made just once for each element,\n"
306 "but the order in which the calls are made on the elements is\n"
307 "unspecified.\n"
308 "\n"
309 "The equality calls are always @code{(pred x elem)}, ie.@: the\n"
310 "given @var{x} is first. This means for instance elements\n"
311 "greater than 5 can be deleted with @code{(delete 5 lst <)}.\n"
312 "\n"
313 "@var{lst} is not modified, but the returned list might share a\n"
314 "common tail with @var{lst}.")
315 #define FUNC_NAME s_scm_srfi1_delete
316 {
317 SCM ret, *p, keeplst;
318 int count;
319
320 if (SCM_UNBNDP (pred))
321 return scm_delete (x, lst);
322
323 SCM_ASSERT (scm_is_true (scm_procedure_p (pred)), pred, SCM_ARG3, FUNC_NAME);
324
325 /* ret is the return list being constructed. p is where to append to it,
326 initially &ret then SCM_CDRLOC of the last pair. lst progresses as
327 elements are considered.
328
329 Elements to be retained are not immediately copied, instead keeplst is
330 the last pair in lst which is to be retained but not yet copied, count
331 is how many from there are wanted. When there's no more deletions, *p
332 can be set to keeplst to share the remainder of the original lst. (The
333 entire original lst if there's no deletions at all.) */
334
335 keeplst = lst;
336 count = 0;
337 p = &ret;
338
339 for ( ; scm_is_pair (lst); lst = SCM_CDR (lst))
340 {
341 if (scm_is_true (scm_call_2 (pred, x, SCM_CAR (lst))))
342 {
343 /* delete this element, so copy those at keeplst */
344 p = list_copy_part (keeplst, count, p);
345 keeplst = SCM_CDR (lst);
346 count = 0;
347 }
348 else
349 {
350 /* keep this element */
351 count++;
352 }
353 }
354
355 /* final retained elements */
356 *p = keeplst;
357
358 /* demand that lst was a proper list */
359 SCM_ASSERT_TYPE (SCM_NULL_OR_NIL_P (lst), lst, SCM_ARG2, FUNC_NAME, "list");
360
361 return ret;
362 }
363 #undef FUNC_NAME
364
365
366 SCM_DEFINE (scm_srfi1_delete_x, "delete!", 2, 1, 0,
367 (SCM x, SCM lst, SCM pred),
368 "Return a list containing the elements of @var{lst} but with\n"
369 "those equal to @var{x} deleted. The returned elements will be\n"
370 "in the same order as they were in @var{lst}.\n"
371 "\n"
372 "Equality is determined by @var{pred}, or @code{equal?} if not\n"
373 "given. An equality call is made just once for each element,\n"
374 "but the order in which the calls are made on the elements is\n"
375 "unspecified.\n"
376 "\n"
377 "The equality calls are always @code{(pred x elem)}, ie.@: the\n"
378 "given @var{x} is first. This means for instance elements\n"
379 "greater than 5 can be deleted with @code{(delete 5 lst <)}.\n"
380 "\n"
381 "@var{lst} may be modified to construct the returned list.")
382 #define FUNC_NAME s_scm_srfi1_delete_x
383 {
384 SCM walk;
385 SCM *prev;
386
387 if (SCM_UNBNDP (pred))
388 return scm_delete_x (x, lst);
389
390 SCM_ASSERT (scm_is_true (scm_procedure_p (pred)), pred, SCM_ARG3, FUNC_NAME);
391
392 for (prev = &lst, walk = lst;
393 scm_is_pair (walk);
394 walk = SCM_CDR (walk))
395 {
396 if (scm_is_true (scm_call_2 (pred, x, SCM_CAR (walk))))
397 *prev = SCM_CDR (walk);
398 else
399 prev = SCM_CDRLOC (walk);
400 }
401
402 /* demand the input was a proper list */
403 SCM_ASSERT_TYPE (SCM_NULL_OR_NIL_P (walk), walk, SCM_ARG2, FUNC_NAME,"list");
404 return lst;
405 }
406 #undef FUNC_NAME
407
408
409 SCM_DEFINE (scm_srfi1_delete_duplicates, "delete-duplicates", 1, 1, 0,
410 (SCM lst, SCM pred),
411 "Return a list containing the elements of @var{lst} but without\n"
412 "duplicates.\n"
413 "\n"
414 "When elements are equal, only the first in @var{lst} is\n"
415 "retained. Equal elements can be anywhere in @var{lst}, they\n"
416 "don't have to be adjacent. The returned list will have the\n"
417 "retained elements in the same order as they were in @var{lst}.\n"
418 "\n"
419 "Equality is determined by @var{pred}, or @code{equal?} if not\n"
420 "given. Calls @code{(pred x y)} are made with element @var{x}\n"
421 "being before @var{y} in @var{lst}. A call is made at most once\n"
422 "for each combination, but the sequence of the calls across the\n"
423 "elements is unspecified.\n"
424 "\n"
425 "@var{lst} is not modified, but the return might share a common\n"
426 "tail with @var{lst}.\n"
427 "\n"
428 "In the worst case, this is an @math{O(N^2)} algorithm because\n"
429 "it must check each element against all those preceding it. For\n"
430 "long lists it is more efficient to sort and then compare only\n"
431 "adjacent elements.")
432 #define FUNC_NAME s_scm_srfi1_delete_duplicates
433 {
434 scm_t_trampoline_2 equal_p;
435 SCM ret, *p, keeplst, item, l;
436 int count, i;
437
438 /* ret is the new list constructed. p is where to append, initially &ret
439 then SCM_CDRLOC of the last pair. lst is advanced as each element is
440 considered.
441
442 Elements retained are not immediately appended to ret, instead keeplst
443 is the last pair in lst which is to be kept but is not yet copied.
444 Initially this is the first pair of lst, since the first element is
445 always retained.
446
447 *p is kept set to keeplst, so ret (inclusive) to lst (exclusive) is all
448 the elements retained, making the equality search loop easy.
449
450 If an item must be deleted, elements from keeplst (inclusive) to lst
451 (exclusive) must be copied and appended to ret. When there's no more
452 deletions, *p is left set to keeplst, so ret shares structure with the
453 original lst. (ret will be the entire original lst if there are no
454 deletions.) */
455
456 /* skip to end if an empty list (or something invalid) */
457 ret = SCM_EOL;
458
459 if (SCM_UNBNDP (pred))
460 equal_p = equal_trampoline;
461 else
462 {
463 SCM_VALIDATE_PROC (SCM_ARG2, pred);
464 equal_p = scm_call_2;
465 }
466
467 keeplst = lst;
468 count = 0;
469 p = &ret;
470
471 for ( ; scm_is_pair (lst); lst = SCM_CDR (lst))
472 {
473 item = SCM_CAR (lst);
474
475 /* look for item in "ret" list */
476 for (l = ret; scm_is_pair (l); l = SCM_CDR (l))
477 {
478 if (scm_is_true (equal_p (pred, SCM_CAR (l), item)))
479 {
480 /* "item" is a duplicate, so copy keeplst onto ret */
481 duplicate:
482 p = list_copy_part (keeplst, count, p);
483
484 keeplst = SCM_CDR (lst); /* elem after the one deleted */
485 count = 0;
486 goto next_elem;
487 }
488 }
489
490 /* look for item in "keeplst" list
491 be careful traversing, in case nasty code changed the cdrs */
492 for (i = 0, l = keeplst;
493 i < count && scm_is_pair (l);
494 i++, l = SCM_CDR (l))
495 if (scm_is_true (equal_p (pred, SCM_CAR (l), item)))
496 goto duplicate;
497
498 /* keep this element */
499 count++;
500
501 next_elem:
502 ;
503 }
504 SCM_ASSERT_TYPE (SCM_NULL_OR_NIL_P (lst), lst, SCM_ARG1, FUNC_NAME, "list");
505
506 /* share tail of keeplst items */
507 *p = keeplst;
508
509 return ret;
510 }
511 #undef FUNC_NAME
512
513
514 SCM_DEFINE (scm_srfi1_delete_duplicates_x, "delete-duplicates!", 1, 1, 0,
515 (SCM lst, SCM pred),
516 "Return a list containing the elements of @var{lst} but without\n"
517 "duplicates.\n"
518 "\n"
519 "When elements are equal, only the first in @var{lst} is\n"
520 "retained. Equal elements can be anywhere in @var{lst}, they\n"
521 "don't have to be adjacent. The returned list will have the\n"
522 "retained elements in the same order as they were in @var{lst}.\n"
523 "\n"
524 "Equality is determined by @var{pred}, or @code{equal?} if not\n"
525 "given. Calls @code{(pred x y)} are made with element @var{x}\n"
526 "being before @var{y} in @var{lst}. A call is made at most once\n"
527 "for each combination, but the sequence of the calls across the\n"
528 "elements is unspecified.\n"
529 "\n"
530 "@var{lst} may be modified to construct the returned list.\n"
531 "\n"
532 "In the worst case, this is an @math{O(N^2)} algorithm because\n"
533 "it must check each element against all those preceding it. For\n"
534 "long lists it is more efficient to sort and then compare only\n"
535 "adjacent elements.")
536 #define FUNC_NAME s_scm_srfi1_delete_duplicates_x
537 {
538 scm_t_trampoline_2 equal_p;
539 SCM ret, endret, item, l;
540
541 /* ret is the return list, constructed from the pairs in lst. endret is
542 the last pair of ret, initially the first pair. lst is advanced as
543 elements are considered. */
544
545 /* skip to end if an empty list (or something invalid) */
546 ret = lst;
547 if (scm_is_pair (lst))
548 {
549 if (SCM_UNBNDP (pred))
550 equal_p = equal_trampoline;
551 else
552 {
553 SCM_VALIDATE_PROC (SCM_ARG2, pred);
554 equal_p = scm_call_2;
555 }
556
557 endret = ret;
558
559 /* loop over lst elements starting from second */
560 for (;;)
561 {
562 lst = SCM_CDR (lst);
563 if (! scm_is_pair (lst))
564 break;
565 item = SCM_CAR (lst);
566
567 /* is item equal to any element from ret to endret (inclusive)? */
568 l = ret;
569 for (;;)
570 {
571 if (scm_is_true (equal_p (pred, SCM_CAR (l), item)))
572 break; /* equal, forget this element */
573
574 if (scm_is_eq (l, endret))
575 {
576 /* not equal to any, so append this pair */
577 SCM_SETCDR (endret, lst);
578 endret = lst;
579 break;
580 }
581 l = SCM_CDR (l);
582 }
583 }
584
585 /* terminate, in case last element was deleted */
586 SCM_SETCDR (endret, SCM_EOL);
587 }
588
589 /* demand that lst was a proper list */
590 SCM_ASSERT_TYPE (SCM_NULL_OR_NIL_P (lst), lst, SCM_ARG1, FUNC_NAME, "list");
591
592 return ret;
593 }
594 #undef FUNC_NAME
595
596
597 SCM_DEFINE (scm_srfi1_drop_right, "drop-right", 2, 0, 0,
598 (SCM lst, SCM n),
599 "Return a new list containing all except the last @var{n}\n"
600 "elements of @var{lst}.")
601 #define FUNC_NAME s_scm_srfi1_drop_right
602 {
603 SCM tail = scm_list_tail (lst, n);
604 SCM ret = SCM_EOL;
605 SCM *rend = &ret;
606 while (scm_is_pair (tail))
607 {
608 *rend = scm_cons (SCM_CAR (lst), SCM_EOL);
609 rend = SCM_CDRLOC (*rend);
610
611 lst = SCM_CDR (lst);
612 tail = SCM_CDR (tail);
613 }
614 SCM_ASSERT_TYPE (SCM_NULL_OR_NIL_P(tail), tail, SCM_ARG1, FUNC_NAME, "list");
615 return ret;
616 }
617 #undef FUNC_NAME
618
619 SCM_DEFINE (scm_srfi1_filter_map, "filter-map", 2, 0, 1,
620 (SCM proc, SCM list1, SCM rest),
621 "Apply @var{proc} to to the elements of @var{list1} @dots{} and\n"
622 "return a list of the results as per SRFI-1 @code{map}, except\n"
623 "that any @code{#f} results are omitted from the list returned.")
624 #define FUNC_NAME s_scm_srfi1_filter_map
625 {
626 SCM ret, *loc, elem, newcell, lst;
627 int argnum;
628
629 SCM_VALIDATE_REST_ARGUMENT (rest);
630
631 ret = SCM_EOL;
632 loc = &ret;
633
634 if (scm_is_null (rest))
635 {
636 /* one list */
637 SCM_VALIDATE_PROC (SCM_ARG1, proc);
638
639 for ( ; scm_is_pair (list1); list1 = SCM_CDR (list1))
640 {
641 elem = scm_call_1 (proc, SCM_CAR (list1));
642 if (scm_is_true (elem))
643 {
644 newcell = scm_cons (elem, SCM_EOL);
645 *loc = newcell;
646 loc = SCM_CDRLOC (newcell);
647 }
648 }
649
650 /* check below that list1 is a proper list, and done */
651 end_list1:
652 lst = list1;
653 argnum = 2;
654 }
655 else if (scm_is_null (SCM_CDR (rest)))
656 {
657 /* two lists */
658 SCM list2 = SCM_CAR (rest);
659 SCM_VALIDATE_PROC (SCM_ARG1, proc);
660
661 for (;;)
662 {
663 if (! scm_is_pair (list1))
664 goto end_list1;
665 if (! scm_is_pair (list2))
666 {
667 lst = list2;
668 argnum = 3;
669 goto check_lst_and_done;
670 }
671 elem = scm_call_2 (proc, SCM_CAR (list1), SCM_CAR (list2));
672 if (scm_is_true (elem))
673 {
674 newcell = scm_cons (elem, SCM_EOL);
675 *loc = newcell;
676 loc = SCM_CDRLOC (newcell);
677 }
678 list1 = SCM_CDR (list1);
679 list2 = SCM_CDR (list2);
680 }
681 }
682 else
683 {
684 /* three or more lists */
685 SCM vec, args, a;
686 size_t len, i;
687
688 /* vec is the list arguments */
689 vec = scm_vector (scm_cons (list1, rest));
690 len = SCM_SIMPLE_VECTOR_LENGTH (vec);
691
692 /* args is the argument list to pass to proc, same length as vec,
693 re-used for each call */
694 args = scm_make_list (SCM_I_MAKINUM (len), SCM_UNDEFINED);
695
696 for (;;)
697 {
698 /* first elem of each list in vec into args, and step those
699 vec entries onto their next element */
700 for (i = 0, a = args, argnum = 2;
701 i < len;
702 i++, a = SCM_CDR (a), argnum++)
703 {
704 lst = SCM_SIMPLE_VECTOR_REF (vec, i); /* list argument */
705 if (! scm_is_pair (lst))
706 goto check_lst_and_done;
707 SCM_SETCAR (a, SCM_CAR (lst)); /* arg for proc */
708 SCM_SIMPLE_VECTOR_SET (vec, i, SCM_CDR (lst)); /* rest of lst */
709 }
710
711 elem = scm_apply (proc, args, SCM_EOL);
712 if (scm_is_true (elem))
713 {
714 newcell = scm_cons (elem, SCM_EOL);
715 *loc = newcell;
716 loc = SCM_CDRLOC (newcell);
717 }
718 }
719 }
720
721 check_lst_and_done:
722 SCM_ASSERT_TYPE (SCM_NULL_OR_NIL_P (lst), lst, argnum, FUNC_NAME, "list");
723 return ret;
724 }
725 #undef FUNC_NAME
726
727
728 SCM_DEFINE (scm_srfi1_find, "find", 2, 0, 0,
729 (SCM pred, SCM lst),
730 "Return the first element of @var{lst} which satisfies the\n"
731 "predicate @var{pred}, or return @code{#f} if no such element is\n"
732 "found.")
733 #define FUNC_NAME s_scm_srfi1_find
734 {
735 SCM_VALIDATE_PROC (SCM_ARG1, pred);
736
737 for ( ; scm_is_pair (lst); lst = SCM_CDR (lst))
738 {
739 SCM elem = SCM_CAR (lst);
740 if (scm_is_true (scm_call_1 (pred, elem)))
741 return elem;
742 }
743 SCM_ASSERT_TYPE (SCM_NULL_OR_NIL_P (lst), lst, SCM_ARG2, FUNC_NAME, "list");
744
745 return SCM_BOOL_F;
746 }
747 #undef FUNC_NAME
748
749
750 SCM_DEFINE (scm_srfi1_find_tail, "find-tail", 2, 0, 0,
751 (SCM pred, SCM lst),
752 "Return the first pair of @var{lst} whose @sc{car} satisfies the\n"
753 "predicate @var{pred}, or return @code{#f} if no such element is\n"
754 "found.")
755 #define FUNC_NAME s_scm_srfi1_find_tail
756 {
757 SCM_VALIDATE_PROC (SCM_ARG1, pred);
758
759 for ( ; scm_is_pair (lst); lst = SCM_CDR (lst))
760 if (scm_is_true (scm_call_1 (pred, SCM_CAR (lst))))
761 return lst;
762 SCM_ASSERT_TYPE (SCM_NULL_OR_NIL_P (lst), lst, SCM_ARG2, FUNC_NAME, "list");
763
764 return SCM_BOOL_F;
765 }
766 #undef FUNC_NAME
767
768 SCM_DEFINE (scm_srfi1_length_plus, "length+", 1, 0, 0,
769 (SCM lst),
770 "Return the length of @var{lst}, or @code{#f} if @var{lst} is\n"
771 "circular.")
772 #define FUNC_NAME s_scm_srfi1_length_plus
773 {
774 long len = scm_ilength (lst);
775 return (len >= 0 ? SCM_I_MAKINUM (len) : SCM_BOOL_F);
776 }
777 #undef FUNC_NAME
778
779
780 /* This routine differs from the core list-copy in allowing improper lists.
781 Maybe the core could allow them similarly. */
782
783 SCM_DEFINE (scm_srfi1_list_copy, "list-copy", 1, 0, 0,
784 (SCM lst),
785 "Return a copy of the given list @var{lst}.\n"
786 "\n"
787 "@var{lst} can be a proper or improper list. And if @var{lst}\n"
788 "is not a pair then it's treated as the final tail of an\n"
789 "improper list and simply returned.")
790 #define FUNC_NAME s_scm_srfi1_list_copy
791 {
792 SCM newlst;
793 SCM * fill_here;
794 SCM from_here;
795
796 newlst = lst;
797 fill_here = &newlst;
798 from_here = lst;
799
800 while (scm_is_pair (from_here))
801 {
802 SCM c;
803 c = scm_cons (SCM_CAR (from_here), SCM_CDR (from_here));
804 *fill_here = c;
805 fill_here = SCM_CDRLOC (c);
806 from_here = SCM_CDR (from_here);
807 }
808 return newlst;
809 }
810 #undef FUNC_NAME
811
812 SCM_DEFINE (scm_srfi1_lset_difference_x, "lset-difference!", 2, 0, 1,
813 (SCM equal, SCM lst, SCM rest),
814 "Return @var{lst} with any elements in the lists in @var{rest}\n"
815 "removed (ie.@: subtracted). For only one @var{lst} argument,\n"
816 "just that list is returned.\n"
817 "\n"
818 "The given @var{equal} procedure is used for comparing elements,\n"
819 "called as @code{(@var{equal} elem1 elemN)}. The first argument\n"
820 "is from @var{lst} and the second from one of the subsequent\n"
821 "lists. But exactly which calls are made and in what order is\n"
822 "unspecified.\n"
823 "\n"
824 "@example\n"
825 "(lset-difference! eqv? (list 'x 'y)) @result{} (x y)\n"
826 "(lset-difference! eqv? (list 1 2 3) '(3 1)) @result{} (2)\n"
827 "(lset-difference! eqv? (list 1 2 3) '(3) '(2)) @result{} (1)\n"
828 "@end example\n"
829 "\n"
830 "@code{lset-difference!} may modify @var{lst} to form its\n"
831 "result.")
832 #define FUNC_NAME s_scm_srfi1_lset_difference_x
833 {
834 SCM ret, *pos, elem, r, b;
835 int argnum;
836
837 SCM_VALIDATE_PROC (SCM_ARG1, equal);
838 SCM_VALIDATE_REST_ARGUMENT (rest);
839
840 ret = SCM_EOL;
841 pos = &ret;
842 for ( ; scm_is_pair (lst); lst = SCM_CDR (lst))
843 {
844 elem = SCM_CAR (lst);
845
846 for (r = rest, argnum = SCM_ARG3;
847 scm_is_pair (r);
848 r = SCM_CDR (r), argnum++)
849 {
850 for (b = SCM_CAR (r); scm_is_pair (b); b = SCM_CDR (b))
851 if (scm_is_true (scm_call_2 (equal, elem, SCM_CAR (b))))
852 goto next_elem; /* equal to elem, so drop that elem */
853
854 SCM_ASSERT_TYPE (SCM_NULL_OR_NIL_P (b), b, argnum, FUNC_NAME,"list");
855 }
856
857 /* elem not equal to anything in later lists, so keep it */
858 *pos = lst;
859 pos = SCM_CDRLOC (lst);
860
861 next_elem:
862 ;
863 }
864 SCM_ASSERT_TYPE (SCM_NULL_OR_NIL_P (lst), lst, SCM_ARG2, FUNC_NAME, "list");
865
866 *pos = SCM_EOL;
867 return ret;
868 }
869 #undef FUNC_NAME
870
871
872 /* Typechecking for multi-argument MAP and FOR-EACH.
873
874 Verify that each element of the vector ARGV, except for the first,
875 is a list and return minimum length. Attribute errors to WHO,
876 and claim that the i'th element of ARGV is WHO's i+2'th argument. */
877 static inline int
878 check_map_args (SCM argv,
879 long len,
880 SCM gf,
881 SCM proc,
882 SCM args,
883 const char *who)
884 {
885 long i;
886 SCM elt;
887
888 for (i = SCM_SIMPLE_VECTOR_LENGTH (argv) - 1; i >= 1; i--)
889 {
890 long elt_len;
891 elt = SCM_SIMPLE_VECTOR_REF (argv, i);
892
893 if (!(scm_is_null (elt) || scm_is_pair (elt)))
894 goto check_map_error;
895
896 elt_len = srfi1_ilength (elt);
897 if (elt_len < -1)
898 goto check_map_error;
899
900 if (len < 0 || (elt_len >= 0 && elt_len < len))
901 len = elt_len;
902 }
903
904 if (len < 0)
905 {
906 /* i == 0 */
907 elt = SCM_EOL;
908 check_map_error:
909 if (gf)
910 scm_apply_generic (gf, scm_cons (proc, args));
911 else
912 scm_wrong_type_arg (who, i + 2, elt);
913 }
914
915 scm_remember_upto_here_1 (argv);
916 return len;
917 }
918
919
920 SCM_GPROC (s_srfi1_map, "map", 2, 0, 1, scm_srfi1_map, g_srfi1_map);
921
922 /* Note: Currently, scm_srfi1_map applies PROC to the argument list(s)
923 sequentially, starting with the first element(s). This is used in
924 the Scheme procedure `map-in-order', which guarantees sequential
925 behaviour, is implemented using scm_map. If the behaviour changes,
926 we need to update `map-in-order'.
927 */
928
929 SCM
930 scm_srfi1_map (SCM proc, SCM arg1, SCM args)
931 #define FUNC_NAME s_srfi1_map
932 {
933 long i, len;
934 SCM res = SCM_EOL;
935 SCM *pres = &res;
936
937 len = srfi1_ilength (arg1);
938 SCM_GASSERTn ((scm_is_null (arg1) || scm_is_pair (arg1)) && len >= -1,
939 g_srfi1_map,
940 scm_cons2 (proc, arg1, args), SCM_ARG2, s_srfi1_map);
941 SCM_VALIDATE_REST_ARGUMENT (args);
942 if (scm_is_null (args))
943 {
944 SCM_GASSERT2 (scm_is_true (scm_procedure_p (proc)), g_srfi1_map,
945 proc, arg1, SCM_ARG1, s_srfi1_map);
946 SCM_GASSERT2 (len >= 0, g_srfi1_map, proc, arg1, SCM_ARG2, s_srfi1_map);
947 while (SCM_NIMP (arg1))
948 {
949 *pres = scm_list_1 (scm_call_1 (proc, SCM_CAR (arg1)));
950 pres = SCM_CDRLOC (*pres);
951 arg1 = SCM_CDR (arg1);
952 }
953 return res;
954 }
955 if (scm_is_null (SCM_CDR (args)))
956 {
957 SCM arg2 = SCM_CAR (args);
958 int len2 = srfi1_ilength (arg2);
959 SCM_GASSERTn (scm_is_true (scm_procedure_p (proc)), g_srfi1_map,
960 scm_cons2 (proc, arg1, args), SCM_ARG1, s_srfi1_map);
961 if (len < 0 || (len2 >= 0 && len2 < len))
962 len = len2;
963 SCM_GASSERTn ((scm_is_null (arg2) || scm_is_pair (arg2))
964 && len >= 0 && len2 >= -1,
965 g_srfi1_map,
966 scm_cons2 (proc, arg1, args),
967 len2 >= 0 ? SCM_ARG2 : SCM_ARG3,
968 s_srfi1_map);
969 while (len > 0)
970 {
971 *pres = scm_list_1 (scm_call_2 (proc, SCM_CAR (arg1), SCM_CAR (arg2)));
972 pres = SCM_CDRLOC (*pres);
973 arg1 = SCM_CDR (arg1);
974 arg2 = SCM_CDR (arg2);
975 --len;
976 }
977 return res;
978 }
979 args = scm_vector (arg1 = scm_cons (arg1, args));
980 len = check_map_args (args, len, g_srfi1_map, proc, arg1, s_srfi1_map);
981 while (len > 0)
982 {
983 arg1 = SCM_EOL;
984 for (i = SCM_SIMPLE_VECTOR_LENGTH (args) - 1; i >= 0; i--)
985 {
986 SCM elt = SCM_SIMPLE_VECTOR_REF (args, i);
987 arg1 = scm_cons (SCM_CAR (elt), arg1);
988 SCM_SIMPLE_VECTOR_SET (args, i, SCM_CDR (elt));
989 }
990 *pres = scm_list_1 (scm_apply (proc, arg1, SCM_EOL));
991 pres = SCM_CDRLOC (*pres);
992 --len;
993 }
994 return res;
995 }
996 #undef FUNC_NAME
997
998 SCM_REGISTER_PROC (s_srfi1_map_in_order, "map-in-order", 2, 0, 1, scm_srfi1_map);
999
1000 SCM_GPROC (s_srfi1_for_each, "for-each", 2, 0, 1, scm_srfi1_for_each, g_srfi1_for_each);
1001
1002 SCM
1003 scm_srfi1_for_each (SCM proc, SCM arg1, SCM args)
1004 #define FUNC_NAME s_srfi1_for_each
1005 {
1006 long i, len;
1007 len = srfi1_ilength (arg1);
1008 SCM_GASSERTn ((scm_is_null (arg1) || scm_is_pair (arg1)) && len >= -1,
1009 g_srfi1_for_each, scm_cons2 (proc, arg1, args),
1010 SCM_ARG2, s_srfi1_for_each);
1011 SCM_VALIDATE_REST_ARGUMENT (args);
1012 if (scm_is_null (args))
1013 {
1014 SCM_GASSERT2 (scm_is_true (scm_procedure_p (proc)), g_srfi1_for_each,
1015 proc, arg1, SCM_ARG1, s_srfi1_for_each);
1016 SCM_GASSERT2 (len >= 0, g_srfi1_for_each, proc, arg1,
1017 SCM_ARG2, s_srfi1_map);
1018 while (SCM_NIMP (arg1))
1019 {
1020 scm_call_1 (proc, SCM_CAR (arg1));
1021 arg1 = SCM_CDR (arg1);
1022 }
1023 return SCM_UNSPECIFIED;
1024 }
1025 if (scm_is_null (SCM_CDR (args)))
1026 {
1027 SCM arg2 = SCM_CAR (args);
1028 int len2 = srfi1_ilength (arg2);
1029 SCM_GASSERTn (scm_is_true (scm_procedure_p (proc)), g_srfi1_for_each,
1030 scm_cons2 (proc, arg1, args), SCM_ARG1, s_srfi1_for_each);
1031 if (len < 0 || (len2 >= 0 && len2 < len))
1032 len = len2;
1033 SCM_GASSERTn ((scm_is_null (arg2) || scm_is_pair (arg2))
1034 && len >= 0 && len2 >= -1,
1035 g_srfi1_for_each,
1036 scm_cons2 (proc, arg1, args),
1037 len2 >= 0 ? SCM_ARG2 : SCM_ARG3,
1038 s_srfi1_for_each);
1039 while (len > 0)
1040 {
1041 scm_call_2 (proc, SCM_CAR (arg1), SCM_CAR (arg2));
1042 arg1 = SCM_CDR (arg1);
1043 arg2 = SCM_CDR (arg2);
1044 --len;
1045 }
1046 return SCM_UNSPECIFIED;
1047 }
1048 args = scm_vector (arg1 = scm_cons (arg1, args));
1049 len = check_map_args (args, len, g_srfi1_for_each, proc, arg1,
1050 s_srfi1_for_each);
1051 while (len > 0)
1052 {
1053 arg1 = SCM_EOL;
1054 for (i = SCM_SIMPLE_VECTOR_LENGTH (args) - 1; i >= 0; i--)
1055 {
1056 SCM elt = SCM_SIMPLE_VECTOR_REF (args, i);
1057 arg1 = scm_cons (SCM_CAR (elt), arg1);
1058 SCM_SIMPLE_VECTOR_SET (args, i, SCM_CDR (elt));
1059 }
1060 scm_apply (proc, arg1, SCM_EOL);
1061 --len;
1062 }
1063 return SCM_UNSPECIFIED;
1064 }
1065 #undef FUNC_NAME
1066
1067
1068 SCM_DEFINE (scm_srfi1_member, "member", 2, 1, 0,
1069 (SCM x, SCM lst, SCM pred),
1070 "Return the first sublist of @var{lst} whose @sc{car} is equal\n"
1071 "to @var{x}. If @var{x} does not appear in @var{lst}, return\n"
1072 "@code{#f}.\n"
1073 "\n"
1074 "Equality is determined by @code{equal?}, or by the equality\n"
1075 "predicate @var{=} if given. @var{=} is called @code{(= @var{x}\n"
1076 "elem)}, ie.@: with the given @var{x} first, so for example to\n"
1077 "find the first element greater than 5,\n"
1078 "\n"
1079 "@example\n"
1080 "(member 5 '(3 5 1 7 2 9) <) @result{} (7 2 9)\n"
1081 "@end example\n"
1082 "\n"
1083 "This version of @code{member} extends the core @code{member} by\n"
1084 "accepting an equality predicate.")
1085 #define FUNC_NAME s_scm_srfi1_member
1086 {
1087 scm_t_trampoline_2 equal_p;
1088 SCM_VALIDATE_LIST (2, lst);
1089 if (SCM_UNBNDP (pred))
1090 equal_p = equal_trampoline;
1091 else
1092 {
1093 SCM_VALIDATE_PROC (SCM_ARG3, pred);
1094 equal_p = scm_call_2;
1095 }
1096 for (; !SCM_NULL_OR_NIL_P (lst); lst = SCM_CDR (lst))
1097 {
1098 if (scm_is_true (equal_p (pred, x, SCM_CAR (lst))))
1099 return lst;
1100 }
1101 return SCM_BOOL_F;
1102 }
1103 #undef FUNC_NAME
1104
1105 SCM_DEFINE (scm_srfi1_assoc, "assoc", 2, 1, 0,
1106 (SCM key, SCM alist, SCM pred),
1107 "Behaves like @code{assq} but uses third argument @var{pred?}\n"
1108 "for key comparison. If @var{pred?} is not supplied,\n"
1109 "@code{equal?} is used. (Extended from R5RS.)\n")
1110 #define FUNC_NAME s_scm_srfi1_assoc
1111 {
1112 SCM ls = alist;
1113 scm_t_trampoline_2 equal_p;
1114 if (SCM_UNBNDP (pred))
1115 equal_p = equal_trampoline;
1116 else
1117 {
1118 SCM_VALIDATE_PROC (SCM_ARG3, pred);
1119 equal_p = scm_call_2;
1120 }
1121 for(; scm_is_pair (ls); ls = SCM_CDR (ls))
1122 {
1123 SCM tmp = SCM_CAR (ls);
1124 SCM_ASSERT_TYPE (scm_is_pair (tmp), alist, SCM_ARG2, FUNC_NAME,
1125 "association list");
1126 if (scm_is_true (equal_p (pred, key, SCM_CAR (tmp))))
1127 return tmp;
1128 }
1129 SCM_ASSERT_TYPE (SCM_NULL_OR_NIL_P (ls), alist, SCM_ARG2, FUNC_NAME,
1130 "association list");
1131 return SCM_BOOL_F;
1132 }
1133 #undef FUNC_NAME
1134
1135 SCM_DEFINE (scm_srfi1_partition, "partition", 2, 0, 0,
1136 (SCM pred, SCM list),
1137 "Partition the elements of @var{list} with predicate @var{pred}.\n"
1138 "Return two values: the list of elements satifying @var{pred} and\n"
1139 "the list of elements @emph{not} satisfying @var{pred}. The order\n"
1140 "of the output lists follows the order of @var{list}. @var{list}\n"
1141 "is not mutated. One of the output lists may share memory with @var{list}.\n")
1142 #define FUNC_NAME s_scm_srfi1_partition
1143 {
1144 /* In this implementation, the output lists don't share memory with
1145 list, because it's probably not worth the effort. */
1146 SCM orig_list = list;
1147 SCM kept = scm_cons(SCM_EOL, SCM_EOL);
1148 SCM kept_tail = kept;
1149 SCM dropped = scm_cons(SCM_EOL, SCM_EOL);
1150 SCM dropped_tail = dropped;
1151
1152 SCM_VALIDATE_PROC (SCM_ARG1, pred);
1153
1154 for (; !SCM_NULL_OR_NIL_P (list); list = SCM_CDR(list)) {
1155 SCM elt, new_tail;
1156
1157 /* Make sure LIST is not a dotted list. */
1158 SCM_ASSERT (scm_is_pair (list), orig_list, SCM_ARG2, FUNC_NAME);
1159
1160 elt = SCM_CAR (list);
1161 new_tail = scm_cons (SCM_CAR (list), SCM_EOL);
1162
1163 if (scm_is_true (scm_call_1 (pred, elt))) {
1164 SCM_SETCDR(kept_tail, new_tail);
1165 kept_tail = new_tail;
1166 }
1167 else {
1168 SCM_SETCDR(dropped_tail, new_tail);
1169 dropped_tail = new_tail;
1170 }
1171 }
1172 /* re-use the initial conses for the values list */
1173 SCM_SETCAR(kept, SCM_CDR(kept));
1174 SCM_SETCDR(kept, dropped);
1175 SCM_SETCAR(dropped, SCM_CDR(dropped));
1176 SCM_SETCDR(dropped, SCM_EOL);
1177 return scm_values(kept);
1178 }
1179 #undef FUNC_NAME
1180
1181
1182 SCM_DEFINE (scm_srfi1_partition_x, "partition!", 2, 0, 0,
1183 (SCM pred, SCM lst),
1184 "Split @var{lst} into those elements which do and don't satisfy\n"
1185 "the predicate @var{pred}.\n"
1186 "\n"
1187 "The return is two values (@pxref{Multiple Values}), the first\n"
1188 "being a list of all elements from @var{lst} which satisfy\n"
1189 "@var{pred}, the second a list of those which do not.\n"
1190 "\n"
1191 "The elements in the result lists are in the same order as in\n"
1192 "@var{lst} but the order in which the calls @code{(@var{pred}\n"
1193 "elem)} are made on the list elements is unspecified.\n"
1194 "\n"
1195 "@var{lst} may be modified to construct the return lists.")
1196 #define FUNC_NAME s_scm_srfi1_partition_x
1197 {
1198 SCM tlst, flst, *tp, *fp;
1199
1200 SCM_ASSERT (scm_is_true (scm_procedure_p (pred)), pred, SCM_ARG1, FUNC_NAME);
1201
1202 /* tlst and flst are the lists of true and false elements. tp and fp are
1203 where to store to append to them, initially &tlst and &flst, then
1204 SCM_CDRLOC of the last pair in the respective lists. */
1205
1206 tlst = SCM_EOL;
1207 flst = SCM_EOL;
1208 tp = &tlst;
1209 fp = &flst;
1210
1211 for ( ; scm_is_pair (lst); lst = SCM_CDR (lst))
1212 {
1213 if (scm_is_true (scm_call_1 (pred, SCM_CAR (lst))))
1214 {
1215 *tp = lst;
1216 tp = SCM_CDRLOC (lst);
1217 }
1218 else
1219 {
1220 *fp = lst;
1221 fp = SCM_CDRLOC (lst);
1222 }
1223 }
1224
1225 SCM_ASSERT_TYPE (SCM_NULL_OR_NIL_P (lst), lst, SCM_ARG2, FUNC_NAME, "list");
1226
1227 /* terminate whichever didn't get the last element(s) */
1228 *tp = SCM_EOL;
1229 *fp = SCM_EOL;
1230
1231 return scm_values (scm_list_2 (tlst, flst));
1232 }
1233 #undef FUNC_NAME
1234
1235 SCM_DEFINE (scm_srfi1_remove, "remove", 2, 0, 0,
1236 (SCM pred, SCM list),
1237 "Return a list containing all elements from @var{lst} which do\n"
1238 "not satisfy the predicate @var{pred}. The elements in the\n"
1239 "result list have the same order as in @var{lst}. The order in\n"
1240 "which @var{pred} is applied to the list elements is not\n"
1241 "specified.")
1242 #define FUNC_NAME s_scm_srfi1_remove
1243 {
1244 SCM walk;
1245 SCM *prev;
1246 SCM res = SCM_EOL;
1247 SCM_VALIDATE_PROC (SCM_ARG1, pred);
1248 SCM_VALIDATE_LIST (2, list);
1249
1250 for (prev = &res, walk = list;
1251 scm_is_pair (walk);
1252 walk = SCM_CDR (walk))
1253 {
1254 if (scm_is_false (scm_call_1 (pred, SCM_CAR (walk))))
1255 {
1256 *prev = scm_cons (SCM_CAR (walk), SCM_EOL);
1257 prev = SCM_CDRLOC (*prev);
1258 }
1259 }
1260
1261 return res;
1262 }
1263 #undef FUNC_NAME
1264
1265
1266 SCM_DEFINE (scm_srfi1_remove_x, "remove!", 2, 0, 0,
1267 (SCM pred, SCM list),
1268 "Return a list containing all elements from @var{list} which do\n"
1269 "not satisfy the predicate @var{pred}. The elements in the\n"
1270 "result list have the same order as in @var{list}. The order in\n"
1271 "which @var{pred} is applied to the list elements is not\n"
1272 "specified. @var{list} may be modified to build the return\n"
1273 "list.")
1274 #define FUNC_NAME s_scm_srfi1_remove_x
1275 {
1276 SCM walk;
1277 SCM *prev;
1278 SCM_VALIDATE_PROC (SCM_ARG1, pred);
1279 SCM_VALIDATE_LIST (2, list);
1280
1281 for (prev = &list, walk = list;
1282 scm_is_pair (walk);
1283 walk = SCM_CDR (walk))
1284 {
1285 if (scm_is_false (scm_call_1 (pred, SCM_CAR (walk))))
1286 prev = SCM_CDRLOC (walk);
1287 else
1288 *prev = SCM_CDR (walk);
1289 }
1290
1291 return list;
1292 }
1293 #undef FUNC_NAME
1294
1295
1296 SCM_DEFINE (scm_srfi1_split_at, "split-at", 2, 0, 0,
1297 (SCM lst, SCM n),
1298 "Return two values (multiple values), being a list of the\n"
1299 "elements before index @var{n} in @var{lst}, and a list of those\n"
1300 "after.")
1301 #define FUNC_NAME s_scm_srfi1_split_at
1302 {
1303 size_t nn;
1304 /* pre is a list of elements before the i split point, loc is the CDRLOC
1305 of the last cell, ie. where to store to append to it */
1306 SCM pre = SCM_EOL;
1307 SCM *loc = &pre;
1308
1309 for (nn = scm_to_size_t (n); nn != 0; nn--)
1310 {
1311 SCM_VALIDATE_CONS (SCM_ARG1, lst);
1312
1313 *loc = scm_cons (SCM_CAR (lst), SCM_EOL);
1314 loc = SCM_CDRLOC (*loc);
1315 lst = SCM_CDR(lst);
1316 }
1317 return scm_values (scm_list_2 (pre, lst));
1318 }
1319 #undef FUNC_NAME
1320
1321
1322 SCM_DEFINE (scm_srfi1_split_at_x, "split-at!", 2, 0, 0,
1323 (SCM lst, SCM n),
1324 "Return two values (multiple values), being a list of the\n"
1325 "elements before index @var{n} in @var{lst}, and a list of those\n"
1326 "after. @var{lst} is modified to form those values.")
1327 #define FUNC_NAME s_scm_srfi1_split_at
1328 {
1329 size_t nn;
1330 SCM upto = lst;
1331 SCM *loc = &lst;
1332
1333 for (nn = scm_to_size_t (n); nn != 0; nn--)
1334 {
1335 SCM_VALIDATE_CONS (SCM_ARG1, upto);
1336
1337 loc = SCM_CDRLOC (upto);
1338 upto = SCM_CDR (upto);
1339 }
1340
1341 *loc = SCM_EOL;
1342 return scm_values (scm_list_2 (lst, upto));
1343 }
1344 #undef FUNC_NAME
1345
1346 SCM_DEFINE (scm_srfi1_take_right, "take-right", 2, 0, 0,
1347 (SCM lst, SCM n),
1348 "Return the a list containing the @var{n} last elements of\n"
1349 "@var{lst}.")
1350 #define FUNC_NAME s_scm_srfi1_take_right
1351 {
1352 SCM tail = scm_list_tail (lst, n);
1353 while (scm_is_pair (tail))
1354 {
1355 lst = SCM_CDR (lst);
1356 tail = SCM_CDR (tail);
1357 }
1358 SCM_ASSERT_TYPE (SCM_NULL_OR_NIL_P(tail), tail, SCM_ARG1, FUNC_NAME, "list");
1359 return lst;
1360 }
1361 #undef FUNC_NAME
1362
1363 \f
1364 void
1365 scm_register_srfi_1 (void)
1366 {
1367 scm_c_register_extension ("libguile-" SCM_EFFECTIVE_VERSION,
1368 "scm_init_srfi_1",
1369 (scm_t_extension_init_func)scm_init_srfi_1, NULL);
1370 }
1371
1372 void
1373 scm_init_srfi_1 (void)
1374 {
1375 SCM the_root_module = scm_lookup_closure_module (SCM_BOOL_F);
1376 #ifndef SCM_MAGIC_SNARFER
1377 #include "libguile/srfi-1.x"
1378 #endif
1379 scm_c_extend_primitive_generic
1380 (SCM_VARIABLE_REF (scm_c_module_lookup (the_root_module, "map")),
1381 SCM_VARIABLE_REF (scm_c_lookup ("map")));
1382 scm_c_extend_primitive_generic
1383 (SCM_VARIABLE_REF (scm_c_module_lookup (the_root_module, "for-each")),
1384 SCM_VARIABLE_REF (scm_c_lookup ("for-each")));
1385 }
1386
1387 /* End of srfi-1.c. */