(filter-map): New tests.
[bpt/guile.git] / srfi / srfi-1.scm
CommitLineData
6be07c52
TTN
1;;; srfi-1.scm --- List Library
2
2d411b05 3;; Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
6be07c52 4;;
73be1d9e
MV
5;; This library is free software; you can redistribute it and/or
6;; modify it under the terms of the GNU Lesser General Public
7;; License as published by the Free Software Foundation; either
8;; version 2.1 of the License, or (at your option) any later version.
9;;
10;; This library is distributed in the hope that it will be useful,
6be07c52
TTN
11;; but WITHOUT ANY WARRANTY; without even the implied warranty of
12;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
73be1d9e
MV
13;; Lesser General Public License for more details.
14;;
15;; You should have received a copy of the GNU Lesser General Public
16;; License along with this library; if not, write to the Free Software
17;; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
e9680547
MG
18
19;;; Author: Martin Grabmueller <mgrabmue@cs.tu-berlin.de>
20;;; Date: 2001-06-06
21
22;;; Commentary:
23
6be07c52
TTN
24;; This is an implementation of SRFI-1 (List Library).
25;;
26;; All procedures defined in SRFI-1, which are not already defined in
27;; the Guile core library, are exported. The procedures in this
28;; implementation work, but they have not been tuned for speed or
29;; memory usage.
30;;
31;; This module is fully documented in the Guile Reference Manual.
e9680547
MG
32
33;;; Code:
34
35(define-module (srfi srfi-1)
563058ef 36 :use-module (ice-9 session)
f595ccfe
MD
37 :use-module (ice-9 receive)
38 :export (
e9680547
MG
39;;; Constructors
40 ;; cons <= in the core
41 ;; list <= in the core
42 xcons
43 ;; cons* <= in the core
44 ;; make-list <= in the core
45 list-tabulate
d61261f0 46 list-copy
e9680547 47 circular-list
f595ccfe 48 ;; iota ; Extended.
e9680547
MG
49
50;;; Predicates
51 proper-list?
52 circular-list?
53 dotted-list?
54 ;; pair? <= in the core
55 ;; null? <= in the core
56 null-list?
57 not-pair?
58 list=
59
60;;; Selectors
61 ;; car <= in the core
62 ;; cdr <= in the core
63 ;; caar <= in the core
64 ;; cadr <= in the core
65 ;; cdar <= in the core
2a326497 66 ;; cddr <= in the core
e9680547
MG
67 ;; caaar <= in the core
68 ;; caadr <= in the core
69 ;; cadar <= in the core
70 ;; caddr <= in the core
71 ;; cdaar <= in the core
72 ;; cdadr <= in the core
73 ;; cddar <= in the core
74 ;; cdddr <= in the core
75 ;; caaaar <= in the core
76 ;; caaadr <= in the core
77 ;; caadar <= in the core
78 ;; caaddr <= in the core
79 ;; cadaar <= in the core
80 ;; cadadr <= in the core
81 ;; caddar <= in the core
82 ;; cadddr <= in the core
83 ;; cdaaar <= in the core
84 ;; cdaadr <= in the core
85 ;; cdadar <= in the core
86 ;; cdaddr <= in the core
87 ;; cddaar <= in the core
88 ;; cddadr <= in the core
89 ;; cdddar <= in the core
90 ;; cddddr <= in the core
91 ;; list-ref <= in the core
92 first
93 second
94 third
95 fourth
96 fifth
97 sixth
98 seventh
99 eighth
100 ninth
101 tenth
102 car+cdr
103 take
104 drop
105 take-right
106 drop-right
107 take!
108 drop-right!
109 split-at
110 split-at!
111 last
112 ;; last-pair <= in the core
113
114;;; Miscelleneous: length, append, concatenate, reverse, zip & count
115 ;; length <= in the core
116 length+
117 ;; append <= in the core
118 ;; append! <= in the core
119 concatenate
120 concatenate!
121 ;; reverse <= in the core
122 ;; reverse! <= in the core
123 append-reverse
124 append-reverse!
125 zip
126 unzip1
127 unzip2
128 unzip3
129 unzip4
130 unzip5
131 count
132
133;;; Fold, unfold & map
134 fold
135 fold-right
136 pair-fold
137 pair-fold-right
138 reduce
139 reduce-right
140 unfold
141 unfold-right
f595ccfe
MD
142 ;; map ; Extended.
143 ;; for-each ; Extended.
e9680547
MG
144 append-map
145 append-map!
146 map!
f595ccfe 147 ;; map-in-order ; Extended.
e9680547
MG
148 pair-for-each
149 filter-map
150
151;;; Filtering & partitioning
c614a00b 152 ;; filter <= in the core
e9680547
MG
153 partition
154 remove
c614a00b 155 ;; filter! <= in the core
e9680547
MG
156 partition!
157 remove!
158
159;;; Searching
160 find
161 find-tail
162 take-while
163 take-while!
164 drop-while
165 span
166 span!
167 break
168 break!
169 any
170 every
f595ccfe
MD
171 ;; list-index ; Extended.
172 ;; member ; Extended.
e9680547
MG
173 ;; memq <= in the core
174 ;; memv <= in the core
175
176;;; Deletion
f595ccfe
MD
177 ;; delete ; Extended.
178 ;; delete! ; Extended.
e9680547
MG
179 delete-duplicates
180 delete-duplicates!
181
182;;; Association lists
f595ccfe 183 ;; assoc ; Extended.
e9680547
MG
184 ;; assq <= in the core
185 ;; assv <= in the core
186 alist-cons
187 alist-copy
188 alist-delete
189 alist-delete!
190
191;;; Set operations on lists
192 lset<=
193 lset=
194 lset-adjoin
195 lset-union
196 lset-intersection
197 lset-difference
198 lset-xor
199 lset-diff+intersection
200 lset-union!
201 lset-intersection!
202 lset-difference!
203 lset-xor!
204 lset-diff+intersection!
205
206;;; Primitive side-effects
207 ;; set-car! <= in the core
208 ;; set-cdr! <= in the core
209 )
d61261f0 210 :re-export (cons list cons* make-list pair? null?
b8b0abf0
MD
211 car cdr caar cadr cdar cddr
212 caaar caadr cadar caddr cdaar cdadr cddar cdddr
213 caaaar caaadr caadar caaddr cadaar cadadr caddar cadddr
214 cdaaar cdaadr cdadar cdaddr cddaar cddadr cdddar cddddr
215 list-ref last-pair length append append! reverse reverse!
216 filter filter! memq memv assq assv set-car! set-cdr!)
d61261f0 217 :replace (iota map for-each map-in-order list-copy list-index member
f595ccfe
MD
218 delete delete! assoc)
219 )
e9680547
MG
220
221(cond-expand-provide (current-module) '(srfi-1))
222
ee6aac97
MD
223;; Load the compiled primitives from the shared library.
224;;
bd453596 225(load-extension "libguile-srfi-srfi-1-v-2" "scm_init_srfi_1")
ee6aac97
MD
226
227
e9680547
MG
228;;; Constructors
229
230(define (xcons d a)
231 (cons a d))
232
5753f02f
GH
233;; internal helper, similar to (scsh utilities) check-arg.
234(define (check-arg-type pred arg caller)
235 (if (pred arg)
236 arg
237 (scm-error 'wrong-type-arg caller
238 "Wrong type argument: ~S" (list arg) '())))
239
240;; the srfi spec doesn't seem to forbid inexact integers.
241(define (non-negative-integer? x) (and (integer? x) (>= x 0)))
242
e9680547 243(define (list-tabulate n init-proc)
5753f02f 244 (check-arg-type non-negative-integer? n "list-tabulate")
e9680547 245 (let lp ((n n) (acc '()))
018adcae 246 (if (<= n 0)
e9680547
MG
247 acc
248 (lp (- n 1) (cons (init-proc (- n 1)) acc)))))
249
2d411b05
KR
250(define (circular-list elt1 . elts)
251 (set! elts (cons elt1 elts))
252 (set-cdr! (last-pair elts) elts)
253 elts)
e9680547
MG
254
255(define (iota count . rest)
5753f02f 256 (check-arg-type non-negative-integer? count "iota")
e9680547
MG
257 (let ((start (if (pair? rest) (car rest) 0))
258 (step (if (and (pair? rest) (pair? (cdr rest))) (cadr rest) 1)))
259 (let lp ((n 0) (acc '()))
260 (if (= n count)
261 (reverse! acc)
262 (lp (+ n 1) (cons (+ start (* n step)) acc))))))
263
264;;; Predicates
265
266(define (proper-list? x)
267 (list? x))
268
269(define (circular-list? x)
270 (if (not-pair? x)
271 #f
272 (let lp ((hare (cdr x)) (tortoise x))
273 (if (not-pair? hare)
274 #f
275 (let ((hare (cdr hare)))
276 (if (not-pair? hare)
277 #f
278 (if (eq? hare tortoise)
279 #t
280 (lp (cdr hare) (cdr tortoise)))))))))
281
282(define (dotted-list? x)
283 (cond
284 ((null? x) #f)
285 ((not-pair? x) #t)
286 (else
287 (let lp ((hare (cdr x)) (tortoise x))
288 (cond
289 ((null? hare) #f)
290 ((not-pair? hare) #t)
291 (else
292 (let ((hare (cdr hare)))
513a3bd7 293 (cond
e9680547
MG
294 ((null? hare) #f)
295 ((not-pair? hare) #t)
296 ((eq? hare tortoise) #f)
297 (else
298 (lp (cdr hare) (cdr tortoise)))))))))))
299
300(define (null-list? x)
301 (cond
513a3bd7 302 ((proper-list? x)
e9680547
MG
303 (null? x))
304 ((circular-list? x)
305 #f)
306 (else
307 (error "not a proper list in null-list?"))))
308
309(define (not-pair? x)
310 (not (pair? x)))
311
312(define (list= elt= . rest)
313 (define (lists-equal a b)
314 (let lp ((a a) (b b))
315 (cond ((null? a)
316 (null? b))
317 ((null? b)
318 #f)
319 (else
320 (and (elt= (car a) (car b))
321 (lp (cdr a) (cdr b)))))))
322 (or (null? rest)
323 (let ((first (car rest)))
324 (let lp ((lists rest))
325 (or (null? lists)
326 (and (lists-equal first (car lists))
327 (lp (cdr lists))))))))
328
329;;; Selectors
330
331(define first car)
332(define second cadr)
333(define third caddr)
334(define fourth cadddr)
335(define (fifth x) (car (cddddr x)))
336(define (sixth x) (cadr (cddddr x)))
337(define (seventh x) (caddr (cddddr x)))
338(define (eighth x) (cadddr (cddddr x)))
339(define (ninth x) (car (cddddr (cddddr x))))
340(define (tenth x) (cadr (cddddr (cddddr x))))
341
342(define (car+cdr x) (values (car x) (cdr x)))
343
4dd6bd84
KR
344(define take list-head)
345(define drop list-tail)
346
e9680547
MG
347(define (take-right flist i)
348 (let lp ((n i) (l flist))
e800aa04 349 (if (<= n 0)
e9680547
MG
350 (let lp0 ((s flist) (l l))
351 (if (null? l)
352 s
353 (lp0 (cdr s) (cdr l))))
354 (lp (- n 1) (cdr l)))))
513a3bd7 355
e9680547
MG
356(define (drop-right flist i)
357 (let lp ((n i) (l flist))
e800aa04 358 (if (<= n 0)
e9680547
MG
359 (let lp0 ((s flist) (l l) (acc '()))
360 (if (null? l)
361 (reverse! acc)
362 (lp0 (cdr s) (cdr l) (cons (car s) acc))))
363 (lp (- n 1) (cdr l)))))
364
365(define (take! x i)
e800aa04 366 (if (<= i 0)
e9680547
MG
367 '()
368 (let lp ((n (- i 1)) (l x))
e800aa04 369 (if (<= n 0)
513a3bd7 370 (begin
e9680547
MG
371 (set-cdr! l '())
372 x)
373 (lp (- n 1) (cdr l))))))
374
375(define (drop-right! flist i)
e800aa04 376 (if (<= i 0)
e9680547
MG
377 flist
378 (let lp ((n (+ i 1)) (l flist))
e800aa04 379 (if (<= n 0)
e9680547
MG
380 (let lp0 ((s flist) (l l))
381 (if (null? l)
382 (begin
383 (set-cdr! s '())
384 flist)
385 (lp0 (cdr s) (cdr l))))
386 (if (null? l)
387 '()
388 (lp (- n 1) (cdr l)))))))
389
390(define (split-at x i)
391 (let lp ((l x) (n i) (acc '()))
e800aa04 392 (if (<= n 0)
e9680547
MG
393 (values (reverse! acc) l)
394 (lp (cdr l) (- n 1) (cons (car l) acc)))))
395
396(define (split-at! x i)
e800aa04 397 (if (<= i 0)
e9680547
MG
398 (values '() x)
399 (let lp ((l x) (n (- i 1)))
e800aa04 400 (if (<= n 0)
e9680547
MG
401 (let ((tmp (cdr l)))
402 (set-cdr! l '())
403 (values x tmp))
404 (lp (cdr l) (- n 1))))))
405
406(define (last pair)
407 (car (last-pair pair)))
408
409;;; Miscelleneous: length, append, concatenate, reverse, zip & count
410
e9680547
MG
411(define (append-reverse rev-head tail)
412 (let lp ((l rev-head) (acc tail))
413 (if (null? l)
414 acc
415 (lp (cdr l) (cons (car l) acc)))))
416
417(define (append-reverse! rev-head tail)
418 (append-reverse rev-head tail)) ; XXX:optimize
419
420(define (zip clist1 . rest)
421 (let lp ((l (cons clist1 rest)) (acc '()))
422 (if (any null? l)
423 (reverse! acc)
cef248dd 424 (lp (map1 cdr l) (cons (map1 car l) acc)))))
513a3bd7 425
e9680547
MG
426
427(define (unzip1 l)
cef248dd 428 (map1 first l))
e9680547 429(define (unzip2 l)
cef248dd 430 (values (map1 first l) (map1 second l)))
e9680547 431(define (unzip3 l)
cef248dd 432 (values (map1 first l) (map1 second l) (map1 third l)))
e9680547 433(define (unzip4 l)
cef248dd 434 (values (map1 first l) (map1 second l) (map1 third l) (map1 fourth l)))
e9680547 435(define (unzip5 l)
cef248dd
MG
436 (values (map1 first l) (map1 second l) (map1 third l) (map1 fourth l)
437 (map1 fifth l)))
e9680547 438
e9680547
MG
439;;; Fold, unfold & map
440
441(define (fold kons knil list1 . rest)
442 (if (null? rest)
443 (let f ((knil knil) (list1 list1))
444 (if (null? list1)
445 knil
446 (f (kons (car list1) knil) (cdr list1))))
447 (let f ((knil knil) (lists (cons list1 rest)))
448 (if (any null? lists)
449 knil
cef248dd
MG
450 (let ((cars (map1 car lists))
451 (cdrs (map1 cdr lists)))
563058ef 452 (f (apply kons (append! cars (list knil))) cdrs))))))
e9680547
MG
453
454(define (fold-right kons knil clist1 . rest)
455 (if (null? rest)
456 (let f ((list1 clist1))
457 (if (null? list1)
458 knil
459 (kons (car list1) (f (cdr list1)))))
460 (let f ((lists (cons clist1 rest)))
461 (if (any null? lists)
462 knil
cef248dd 463 (apply kons (append! (map1 car lists) (list (f (map1 cdr lists)))))))))
e9680547
MG
464
465(define (pair-fold kons knil clist1 . rest)
466 (if (null? rest)
467 (let f ((knil knil) (list1 clist1))
468 (if (null? list1)
469 knil
470 (let ((tail (cdr list1)))
471 (f (kons list1 knil) tail))))
472 (let f ((knil knil) (lists (cons clist1 rest)))
473 (if (any null? lists)
474 knil
cef248dd 475 (let ((tails (map1 cdr lists)))
563058ef 476 (f (apply kons (append! lists (list knil))) tails))))))
e9680547
MG
477
478
479(define (pair-fold-right kons knil clist1 . rest)
480 (if (null? rest)
481 (let f ((list1 clist1))
482 (if (null? list1)
483 knil
484 (kons list1 (f (cdr list1)))))
485 (let f ((lists (cons clist1 rest)))
486 (if (any null? lists)
487 knil
cef248dd 488 (apply kons (append! lists (list (f (map1 cdr lists)))))))))
e9680547
MG
489
490(define (unfold p f g seed . rest)
491 (let ((tail-gen (if (pair? rest)
492 (if (pair? (cdr rest))
493 (scm-error 'wrong-number-of-args
494 "unfold" "too many arguments" '() '())
495 (car rest))
496 (lambda (x) '()))))
497 (let uf ((seed seed))
498 (if (p seed)
499 (tail-gen seed)
500 (cons (f seed)
501 (uf (g seed)))))))
502
503(define (unfold-right p f g seed . rest)
504 (let ((tail (if (pair? rest)
505 (if (pair? (cdr rest))
506 (scm-error 'wrong-number-of-args
507 "unfold-right" "too many arguments" '()
508 '())
509 (car rest))
510 '())))
511 (let uf ((seed seed) (lis tail))
512 (if (p seed)
513 lis
514 (uf (g seed) (cons (f seed) lis))))))
515
516(define (reduce f ridentity lst)
517 (fold f ridentity lst))
518
519(define (reduce-right f ridentity lst)
520 (fold-right f ridentity lst))
521
cef248dd
MG
522
523;; Internal helper procedure. Map `f' over the single list `ls'.
524;;
7692d26b 525(define map1 map)
cef248dd 526
e9680547
MG
527(define (append-map f clist1 . rest)
528 (if (null? rest)
529 (let lp ((l clist1))
530 (if (null? l)
531 '()
532 (append (f (car l)) (lp (cdr l)))))
533 (let lp ((l (cons clist1 rest)))
534 (if (any1 null? l)
535 '()
cef248dd
MG
536 (append (apply f (map1 car l)) (lp (map1 cdr l)))))))
537
e9680547
MG
538
539(define (append-map! f clist1 . rest)
540 (if (null? rest)
541 (let lp ((l clist1))
542 (if (null? l)
543 '()
544 (append! (f (car l)) (lp (cdr l)))))
545 (let lp ((l (cons clist1 rest)))
546 (if (any1 null? l)
547 '()
cef248dd 548 (append! (apply f (map1 car l)) (lp (map1 cdr l)))))))
e9680547 549
c6424115
KR
550;; OPTIMIZE-ME: Re-use cons cells of list1
551(define map! map)
e9680547
MG
552
553(define (pair-for-each f clist1 . rest)
554 (if (null? rest)
555 (let lp ((l clist1))
556 (if (null? l)
557 (if #f #f)
558 (begin
559 (f l)
560 (lp (cdr l)))))
561 (let lp ((l (cons clist1 rest)))
562 (if (any1 null? l)
563 (if #f #f)
564 (begin
565 (apply f l)
cef248dd 566 (lp (map1 cdr l)))))))
e9680547
MG
567
568(define (filter-map f clist1 . rest)
569 (if (null? rest)
0d09b3ff
KR
570 (let lp ((l clist1)
571 (rl '()))
e9680547 572 (if (null? l)
0d09b3ff 573 (reverse! rl)
e9680547
MG
574 (let ((res (f (car l))))
575 (if res
0d09b3ff
KR
576 (lp (cdr l) (cons res rl))
577 (lp (cdr l) rl)))))
578 (let lp ((l (cons clist1 rest))
579 (rl '()))
e9680547 580 (if (any1 null? l)
0d09b3ff 581 (reverse! rl)
cef248dd 582 (let ((res (apply f (map1 car l))))
e9680547 583 (if res
0d09b3ff
KR
584 (lp (map1 cdr l) (cons res rl))
585 (lp (map1 cdr l) rl)))))))
e9680547
MG
586
587;;; Filtering & partitioning
588
e9680547 589(define (remove pred list)
848458d9 590 (filter (lambda (x) (not (pred x))) list))
e9680547 591
e9680547
MG
592(define (partition! pred list)
593 (partition pred list)) ; XXX:optimize
594
595(define (remove! pred list)
596 (remove pred list)) ; XXX:optimize
597
598;;; Searching
599
600(define (find pred clist)
601 (if (null? clist)
602 #f
603 (if (pred (car clist))
604 (car clist)
605 (find pred (cdr clist)))))
606
607(define (find-tail pred clist)
608 (if (null? clist)
609 #f
610 (if (pred (car clist))
611 clist
612 (find-tail pred (cdr clist)))))
613
e4cb30df
TTN
614(define (take-while pred ls)
615 (cond ((null? ls) '())
616 ((not (pred (car ls))) '())
617 (else
618 (let ((result (list (car ls))))
619 (let lp ((ls (cdr ls)) (p result))
620 (cond ((null? ls) result)
621 ((not (pred (car ls))) result)
622 (else
623 (set-cdr! p (list (car ls)))
624 (lp (cdr ls) (cdr p)))))))))
e9680547
MG
625
626(define (take-while! pred clist)
627 (take-while pred clist)) ; XXX:optimize
628
629(define (drop-while pred clist)
630 (if (null? clist)
631 '()
632 (if (pred (car clist))
633 (drop-while pred (cdr clist))
634 clist)))
635
636(define (span pred clist)
637 (if (null? clist)
638 (values '() '())
639 (if (pred (car clist))
640 (receive (first last) (span pred (cdr clist))
641 (values (cons (car clist) first) last))
642 (values '() clist))))
643
644(define (span! pred list)
645 (span pred list)) ; XXX:optimize
646
647(define (break pred clist)
648 (if (null? clist)
649 (values '() '())
650 (if (pred (car clist))
651 (values '() clist)
652 (receive (first last) (break pred (cdr clist))
653 (values (cons (car clist) first) last)))))
654
655(define (break! pred list)
656 (break pred list)) ; XXX:optimize
657
658(define (any pred ls . lists)
659 (if (null? lists)
660 (any1 pred ls)
661 (let lp ((lists (cons ls lists)))
662 (cond ((any1 null? lists)
663 #f)
cef248dd
MG
664 ((any1 null? (map1 cdr lists))
665 (apply pred (map1 car lists)))
e9680547 666 (else
cef248dd 667 (or (apply pred (map1 car lists)) (lp (map1 cdr lists))))))))
e9680547
MG
668
669(define (any1 pred ls)
670 (let lp ((ls ls))
671 (cond ((null? ls)
672 #f)
673 ((null? (cdr ls))
674 (pred (car ls)))
675 (else
676 (or (pred (car ls)) (lp (cdr ls)))))))
677
678(define (every pred ls . lists)
679 (if (null? lists)
680 (every1 pred ls)
681 (let lp ((lists (cons ls lists)))
682 (cond ((any1 null? lists)
683 #t)
cef248dd
MG
684 ((any1 null? (map1 cdr lists))
685 (apply pred (map1 car lists)))
e9680547 686 (else
cef248dd 687 (and (apply pred (map1 car lists)) (lp (map1 cdr lists))))))))
e9680547
MG
688
689(define (every1 pred ls)
690 (let lp ((ls ls))
691 (cond ((null? ls)
692 #t)
693 ((null? (cdr ls))
694 (pred (car ls)))
695 (else
696 (and (pred (car ls)) (lp (cdr ls)))))))
697
698(define (list-index pred clist1 . rest)
699 (if (null? rest)
700 (let lp ((l clist1) (i 0))
701 (if (null? l)
702 #f
703 (if (pred (car l))
704 i
705 (lp (cdr l) (+ i 1)))))
706 (let lp ((lists (cons clist1 rest)) (i 0))
707 (cond ((any1 null? lists)
708 #f)
cef248dd 709 ((apply pred (map1 car lists)) i)
e9680547 710 (else
cef248dd 711 (lp (map1 cdr lists) (+ i 1)))))))
e9680547 712
e9680547
MG
713;;; Association lists
714
e9680547
MG
715(define (alist-cons key datum alist)
716 (acons key datum alist))
717
718(define (alist-copy alist)
719 (let lp ((a alist))
720 (if (null? a)
721 '()
563058ef 722 (acons (caar a) (cdar a) (lp (cdr a))))))
e9680547
MG
723
724(define (alist-delete key alist . rest)
725 (let ((k= (if (pair? rest) (car rest) equal?)))
726 (let lp ((a alist))
727 (if (null? a)
728 '()
729 (if (k= (caar a) key)
730 (lp (cdr a))
731 (cons (car a) (lp (cdr a))))))))
732
733(define (alist-delete! key alist . rest)
734 (let ((k= (if (pair? rest) (car rest) equal?)))
735 (alist-delete key alist k=))) ; XXX:optimize
736
737;;; Set operations on lists
738
739(define (lset<= = . rest)
740 (if (null? rest)
741 #t
742 (let lp ((f (car rest)) (r (cdr rest)))
743 (or (null? r)
744 (and (every (lambda (el) (member el (car r) =)) f)
745 (lp (car r) (cdr r)))))))
746
747(define (lset= = list1 . rest)
748 (if (null? rest)
749 #t
750 (let lp ((f list1) (r rest))
751 (or (null? r)
752 (and (every (lambda (el) (member el (car r) =)) f)
753 (every (lambda (el) (member el f =)) (car r))
754 (lp (car r) (cdr r)))))))
755
756(define (lset-adjoin = list . rest)
757 (let lp ((l rest) (acc list))
758 (if (null? l)
759 acc
760 (if (member (car l) acc)
761 (lp (cdr l) acc)
762 (lp (cdr l) (cons (car l) acc))))))
763
764(define (lset-union = . rest)
765 (let lp0 ((l rest) (acc '()))
766 (if (null? l)
767 (reverse! acc)
768 (let lp1 ((ll (car l)) (acc acc))
769 (if (null? ll)
770 (lp0 (cdr l) acc)
771 (if (member (car ll) acc =)
772 (lp1 (cdr ll) acc)
773 (lp1 (cdr ll) (cons (car ll) acc))))))))
774
775(define (lset-intersection = list1 . rest)
776 (let lp ((l list1) (acc '()))
777 (if (null? l)
778 (reverse! acc)
779 (if (every (lambda (ll) (member (car l) ll =)) rest)
780 (lp (cdr l) (cons (car l) acc))
781 (lp (cdr l) acc)))))
782
783(define (lset-difference = list1 . rest)
784 (if (null? rest)
785 list1
786 (let lp ((l list1) (acc '()))
787 (if (null? l)
788 (reverse! acc)
789 (if (any (lambda (ll) (member (car l) ll =)) rest)
790 (lp (cdr l) acc)
791 (lp (cdr l) (cons (car l) acc)))))))
792
793;(define (fold kons knil list1 . rest)
794
795(define (lset-xor = . rest)
796 (fold (lambda (lst res)
797 (let lp ((l lst) (acc '()))
798 (if (null? l)
799 (let lp0 ((r res) (acc acc))
800 (if (null? r)
801 (reverse! acc)
802 (if (member (car r) lst =)
803 (lp0 (cdr r) acc)
804 (lp0 (cdr r) (cons (car r) acc)))))
805 (if (member (car l) res =)
806 (lp (cdr l) acc)
807 (lp (cdr l) (cons (car l) acc))))))
808 '()
809 rest))
810
811(define (lset-diff+intersection = list1 . rest)
812 (let lp ((l list1) (accd '()) (acci '()))
813 (if (null? l)
814 (values (reverse! accd) (reverse! acci))
815 (let ((appears (every (lambda (ll) (member (car l) ll =)) rest)))
816 (if appears
817 (lp (cdr l) accd (cons (car l) acci))
818 (lp (cdr l) (cons (car l) accd) acci))))))
819
820
821(define (lset-union! = . rest)
822 (apply lset-union = rest)) ; XXX:optimize
823
824(define (lset-intersection! = list1 . rest)
825 (apply lset-intersection = list1 rest)) ; XXX:optimize
826
827(define (lset-difference! = list1 . rest)
828 (apply lset-difference = list1 rest)) ; XXX:optimize
829
830(define (lset-xor! = . rest)
831 (apply lset-xor = rest)) ; XXX:optimize
832
833(define (lset-diff+intersection! = list1 . rest)
834 (apply lset-diff+intersection = list1 rest)) ; XXX:optimize
6be07c52
TTN
835
836;;; srfi-1.scm ends here