1
2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3;;
4;; MODULE      : iterator.scm
5;; DESCRIPTION : abstract iterators
6;; COPYRIGHT   : (C) 2007  Joris van der Hoeven
7;;
8;; This software falls under the GNU general public license version 3 or later.
9;; It comes WITHOUT ANY WARRANTY WHATSOEVER. For details, see the file LICENSE
10;; in the root directory or <http://www.gnu.org/licenses/gpl-3.0.html>.
11;;
12;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
13
14(texmacs-module (kernel library iterator))
15
16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
17;; Construction of iterators
18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
19
20(define-macro (iterator val next)
21  "Primitive iterator constructor from value @val and next iterator @next."
22  `(lambda () (cons ,val ,next)))
23
24(define-public (range start end)
25  "Range iterator from @start to @end (not included)."
26  (and (< start end)
27       (iterator start (range (+ start 1) end))))
28
29(define-public (list->iterator l)
30  "Convert the list @l to an iterator."
31  (and (nnull? l)
32       (iterator (car l) (list->iterator (cdr l)))))
33
34(define-public (iterator-append . its)
35  "Append the iterators @its."
36  (cond ((null? its) #f)
37	((not (car its)) (apply iterator-append (cdr its)))
38	(else (let* ((next ((car its)))
39		     (cont (cons (cdr next) (cdr its))))
40		(iterator (car next) (apply iterator-append cont))))))
41
42(define-public (iterator-filter it pred?)
43  "Get elements in iterator @it which match the predicate @pred?."
44  (with next #f
45    (while (and it (begin (set! next (it)) (not (pred? (car next)))))
46      (set! it (cdr next)))
47    (and it (lambda () next))))
48
49(define-public-macro (extract var it prop?)
50  "Extract all values @var from iterator @it which match the property @prop?."
51  `(iterator-filter ,it (lambda (,var) ,prop?)))
52
53;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
54;; Traversal of iterators
55;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
56
57(define-public (iterator-value it)
58  "Get current value of iterator @it."
59  (and it (car (it))))
60
61(define-public (iterator-next it)
62  "Get next iterator after @it."
63  (and it (cdr (it))))
64
65(define-public-macro (iterator-read! it)
66  "Read one value from iterator @it."
67  `(and ,it
68	(with next (,it)
69	  (set! ,it (cdr next))
70	  (car next))))
71
72(define-public (iterator-apply it fun)
73  (while it
74    (with next (it)
75      (fun (car next))
76      (set! it (cdr next)))))
77
78(define-public-macro (for-in var-it . body)
79  "Execute @body for values in an iterator."
80  (let* ((var (car var-it))
81	 (it (cadr var-it))
82	 (fun `(lambda (,var) ,@body)))
83    `(iterator-apply ,it ,fun)))
84
85(define-public (iterator->list it)
86  "Convert iterator @it into a list."
87  (if (not it) '()
88      (with next (it)
89	(cons (car next) (iterator->list (cdr next))))))
90