Provide Guile-friendly `coding:' meta-data.
[bpt/guile.git] / module / srfi / srfi-1.scm
1 ;;; srfi-1.scm --- List Library
2
3 ;; Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2009 Free Software Foundation, Inc.
4 ;;
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 3 of the License, or (at your option) any later version.
9 ;;
10 ;; This library 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 ;; 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
19 ;;; Author: Martin Grabmueller <mgrabmue@cs.tu-berlin.de>
20 ;;; Date: 2001-06-06
21
22 ;;; Commentary:
23
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.
32
33 ;;; Code:
34
35 (define-module (srfi srfi-1)
36 :export (
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
44 list-copy
45 circular-list
46 ;; iota ; Extended.
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
64 ;; cddr <= in the core
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
140 ;; map ; Extended.
141 ;; for-each ; Extended.
142 append-map
143 append-map!
144 map!
145 ;; map-in-order ; Extended.
146 pair-for-each
147 filter-map
148
149 ;;; Filtering & partitioning
150 ;; filter <= in the core
151 partition
152 remove
153 ;; filter! <= in the core
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
169 ;; list-index ; Extended.
170 ;; member ; Extended.
171 ;; memq <= in the core
172 ;; memv <= in the core
173
174 ;;; Deletion
175 ;; delete ; Extended.
176 ;; delete! ; Extended.
177 delete-duplicates
178 delete-duplicates!
179
180 ;;; Association lists
181 ;; assoc ; Extended.
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 )
208 :re-export (cons list cons* make-list pair? null?
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!)
215 :replace (iota map for-each map-in-order list-copy list-index member
216 delete delete! assoc)
217 )
218
219 (cond-expand-provide (current-module) '(srfi-1))
220
221 ;; Load the compiled primitives from the shared library.
222 ;;
223 (load-extension "libguile-srfi-srfi-1-v-4" "scm_init_srfi_1")
224
225
226 ;;; Constructors
227
228 ;; internal helper, similar to (scsh utilities) check-arg.
229 (define (check-arg-type pred arg caller)
230 (if (pred arg)
231 arg
232 (scm-error 'wrong-type-arg caller
233 "Wrong type argument: ~S" (list arg) '())))
234
235 ;; the srfi spec doesn't seem to forbid inexact integers.
236 (define (non-negative-integer? x) (and (integer? x) (>= x 0)))
237
238
239
240 (define (circular-list elt1 . elts)
241 (set! elts (cons elt1 elts))
242 (set-cdr! (last-pair elts) elts)
243 elts)
244
245 (define* (iota count #:optional (start 0) (step 1))
246 (check-arg-type non-negative-integer? count "iota")
247 (let lp ((n 0) (acc '()))
248 (if (= n count)
249 (reverse! acc)
250 (lp (+ n 1) (cons (+ start (* n step)) acc)))))
251
252 ;;; Predicates
253
254 (define (proper-list? x)
255 (list? x))
256
257 (define (circular-list? x)
258 (if (not-pair? x)
259 #f
260 (let lp ((hare (cdr x)) (tortoise x))
261 (if (not-pair? hare)
262 #f
263 (let ((hare (cdr hare)))
264 (if (not-pair? hare)
265 #f
266 (if (eq? hare tortoise)
267 #t
268 (lp (cdr hare) (cdr tortoise)))))))))
269
270 (define (dotted-list? x)
271 (cond
272 ((null? x) #f)
273 ((not-pair? x) #t)
274 (else
275 (let lp ((hare (cdr x)) (tortoise x))
276 (cond
277 ((null? hare) #f)
278 ((not-pair? hare) #t)
279 (else
280 (let ((hare (cdr hare)))
281 (cond
282 ((null? hare) #f)
283 ((not-pair? hare) #t)
284 ((eq? hare tortoise) #f)
285 (else
286 (lp (cdr hare) (cdr tortoise)))))))))))
287
288 (define (null-list? x)
289 (cond
290 ((proper-list? x)
291 (null? x))
292 ((circular-list? x)
293 #f)
294 (else
295 (error "not a proper list in null-list?"))))
296
297 (define (list= elt= . rest)
298 (define (lists-equal a b)
299 (let lp ((a a) (b b))
300 (cond ((null? a)
301 (null? b))
302 ((null? b)
303 #f)
304 (else
305 (and (elt= (car a) (car b))
306 (lp (cdr a) (cdr b)))))))
307 (or (null? rest)
308 (let lp ((lists rest))
309 (or (null? (cdr lists))
310 (and (lists-equal (car lists) (cadr lists))
311 (lp (cdr lists)))))))
312
313 ;;; Selectors
314
315 (define first car)
316 (define second cadr)
317 (define third caddr)
318 (define fourth cadddr)
319
320 (define take list-head)
321 (define drop list-tail)
322
323 ;;; Miscelleneous: length, append, concatenate, reverse, zip & count
324
325 (define (zip clist1 . rest)
326 (let lp ((l (cons clist1 rest)) (acc '()))
327 (if (any null? l)
328 (reverse! acc)
329 (lp (map1 cdr l) (cons (map1 car l) acc)))))
330
331
332 (define (unzip1 l)
333 (map1 first l))
334 (define (unzip2 l)
335 (values (map1 first l) (map1 second l)))
336 (define (unzip3 l)
337 (values (map1 first l) (map1 second l) (map1 third l)))
338 (define (unzip4 l)
339 (values (map1 first l) (map1 second l) (map1 third l) (map1 fourth l)))
340 (define (unzip5 l)
341 (values (map1 first l) (map1 second l) (map1 third l) (map1 fourth l)
342 (map1 fifth l)))
343
344 ;;; Fold, unfold & map
345
346 (define (fold-right kons knil clist1 . rest)
347 (if (null? rest)
348 (let f ((list1 clist1))
349 (if (null? list1)
350 knil
351 (kons (car list1) (f (cdr list1)))))
352 (let f ((lists (cons clist1 rest)))
353 (if (any null? lists)
354 knil
355 (apply kons (append! (map1 car lists) (list (f (map1 cdr lists)))))))))
356
357 (define (pair-fold kons knil clist1 . rest)
358 (if (null? rest)
359 (let f ((knil knil) (list1 clist1))
360 (if (null? list1)
361 knil
362 (let ((tail (cdr list1)))
363 (f (kons list1 knil) tail))))
364 (let f ((knil knil) (lists (cons clist1 rest)))
365 (if (any null? lists)
366 knil
367 (let ((tails (map1 cdr lists)))
368 (f (apply kons (append! lists (list knil))) tails))))))
369
370
371 (define (pair-fold-right kons knil clist1 . rest)
372 (if (null? rest)
373 (let f ((list1 clist1))
374 (if (null? list1)
375 knil
376 (kons list1 (f (cdr list1)))))
377 (let f ((lists (cons clist1 rest)))
378 (if (any null? lists)
379 knil
380 (apply kons (append! lists (list (f (map1 cdr lists)))))))))
381
382 (define* (unfold p f g seed #:optional (tail-gen (lambda (x) '())))
383 (let uf ((seed seed))
384 (if (p seed)
385 (tail-gen seed)
386 (cons (f seed)
387 (uf (g seed))))))
388
389 (define* (unfold-right p f g seed #:optional (tail '()))
390 (let uf ((seed seed) (lis tail))
391 (if (p seed)
392 lis
393 (uf (g seed) (cons (f seed) lis)))))
394
395
396 ;; Internal helper procedure. Map `f' over the single list `ls'.
397 ;;
398 (define map1 map)
399
400 (define (append-map f clist1 . rest)
401 (concatenate (apply map f clist1 rest)))
402
403 (define (append-map! f clist1 . rest)
404 (concatenate! (apply map f clist1 rest)))
405
406 ;; OPTIMIZE-ME: Re-use cons cells of list1
407 (define map! map)
408
409 (define (pair-for-each f clist1 . rest)
410 (if (null? rest)
411 (let lp ((l clist1))
412 (if (null? l)
413 (if #f #f)
414 (begin
415 (f l)
416 (lp (cdr l)))))
417 (let lp ((l (cons clist1 rest)))
418 (if (any1 null? l)
419 (if #f #f)
420 (begin
421 (apply f l)
422 (lp (map1 cdr l)))))))
423
424 ;;; Searching
425
426 (define (any pred ls . lists)
427 (if (null? lists)
428 (any1 pred ls)
429 (let lp ((lists (cons ls lists)))
430 (cond ((any1 null? lists)
431 #f)
432 ((any1 null? (map1 cdr lists))
433 (apply pred (map1 car lists)))
434 (else
435 (or (apply pred (map1 car lists)) (lp (map1 cdr lists))))))))
436
437 (define (any1 pred ls)
438 (let lp ((ls ls))
439 (cond ((null? ls)
440 #f)
441 ((null? (cdr ls))
442 (pred (car ls)))
443 (else
444 (or (pred (car ls)) (lp (cdr ls)))))))
445
446 (define (every pred ls . lists)
447 (if (null? lists)
448 (every1 pred ls)
449 (let lp ((lists (cons ls lists)))
450 (cond ((any1 null? lists)
451 #t)
452 ((any1 null? (map1 cdr lists))
453 (apply pred (map1 car lists)))
454 (else
455 (and (apply pred (map1 car lists)) (lp (map1 cdr lists))))))))
456
457 (define (every1 pred ls)
458 (let lp ((ls ls))
459 (cond ((null? ls)
460 #t)
461 ((null? (cdr ls))
462 (pred (car ls)))
463 (else
464 (and (pred (car ls)) (lp (cdr ls)))))))
465
466 ;;; Association lists
467
468 (define alist-cons acons)
469
470 (define* (alist-delete key alist #:optional (k= equal?))
471 (let lp ((a alist) (rl '()))
472 (if (null? a)
473 (reverse! rl)
474 (if (k= key (caar a))
475 (lp (cdr a) rl)
476 (lp (cdr a) (cons (car a) rl))))))
477
478 (define* (alist-delete! key alist #:optional (k= equal?))
479 (alist-delete key alist k=)) ; XXX:optimize
480
481 ;;; Set operations on lists
482
483 (define (lset<= = . rest)
484 (if (null? rest)
485 #t
486 (let lp ((f (car rest)) (r (cdr rest)))
487 (or (null? r)
488 (and (every (lambda (el) (member el (car r) =)) f)
489 (lp (car r) (cdr r)))))))
490
491 (define (lset= = . rest)
492 (if (null? rest)
493 #t
494 (let lp ((f (car rest)) (r (cdr rest)))
495 (or (null? r)
496 (and (every (lambda (el) (member el (car r) =)) f)
497 (every (lambda (el) (member el f (lambda (x y) (= y x)))) (car r))
498 (lp (car r) (cdr r)))))))
499
500 (define (lset-union = . rest)
501 (let ((acc '()))
502 (for-each (lambda (lst)
503 (if (null? acc)
504 (set! acc lst)
505 (for-each (lambda (elem)
506 (if (not (member elem acc
507 (lambda (x y) (= y x))))
508 (set! acc (cons elem acc))))
509 lst)))
510 rest)
511 acc))
512
513 (define (lset-intersection = list1 . rest)
514 (let lp ((l list1) (acc '()))
515 (if (null? l)
516 (reverse! acc)
517 (if (every (lambda (ll) (member (car l) ll =)) rest)
518 (lp (cdr l) (cons (car l) acc))
519 (lp (cdr l) acc)))))
520
521 (define (lset-difference = list1 . rest)
522 (if (null? rest)
523 list1
524 (let lp ((l list1) (acc '()))
525 (if (null? l)
526 (reverse! acc)
527 (if (any (lambda (ll) (member (car l) ll =)) rest)
528 (lp (cdr l) acc)
529 (lp (cdr l) (cons (car l) acc)))))))
530
531 ;(define (fold kons knil list1 . rest)
532
533 (define (lset-xor = . rest)
534 (fold (lambda (lst res)
535 (let lp ((l lst) (acc '()))
536 (if (null? l)
537 (let lp0 ((r res) (acc acc))
538 (if (null? r)
539 (reverse! acc)
540 (if (member (car r) lst =)
541 (lp0 (cdr r) acc)
542 (lp0 (cdr r) (cons (car r) acc)))))
543 (if (member (car l) res =)
544 (lp (cdr l) acc)
545 (lp (cdr l) (cons (car l) acc))))))
546 '()
547 rest))
548
549 (define (lset-diff+intersection = list1 . rest)
550 (let lp ((l list1) (accd '()) (acci '()))
551 (if (null? l)
552 (values (reverse! accd) (reverse! acci))
553 (let ((appears (every (lambda (ll) (member (car l) ll =)) rest)))
554 (if appears
555 (lp (cdr l) accd (cons (car l) acci))
556 (lp (cdr l) (cons (car l) accd) acci))))))
557
558
559 (define (lset-union! = . rest)
560 (apply lset-union = rest)) ; XXX:optimize
561
562 (define (lset-intersection! = list1 . rest)
563 (apply lset-intersection = list1 rest)) ; XXX:optimize
564
565 (define (lset-xor! = . rest)
566 (apply lset-xor = rest)) ; XXX:optimize
567
568 (define (lset-diff+intersection! = list1 . rest)
569 (apply lset-diff+intersection = list1 rest)) ; XXX:optimize
570
571 ;;; srfi-1.scm ends here