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