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