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