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