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