/
iterate.scm
166 lines (136 loc) · 4.81 KB
/
iterate.scm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
;;;
;;; Iterators
;;;
(import "java.lang.Object")
(import "java.lang.String")
(use-module "elf/util.scm" 'import 'all)
(define-method (iterate (mapper jsint.Procedure) action)
(mapper action))
;;; Hashtable and Vector specialization are only needed for JDK 1.1
(define-method (iterate (items java.util.Hashtable) action)
(iterate (.elements items) action))
(define-method (iterate (items java.util.Vector) action)
(iterate (.elements items) action))
(define-method (iterate (items java.util.Enumeration) action)
(let loop ()
(if (.hasMoreElements items)
(begin (action (.nextElement items))
(loop)))))
(when-classes
(java.util.Collection)
(define-method (iterate (items java.util.Map) action)
(iterate (.values items) action))
(define-method (iterate (items java.util.Iterator) action)
(let loop ()
(if (.hasNext items)
(begin (action (.next items))
(loop)))))
(define-method (iterate (items java.util.Collection) action)
(iterate (.iterator items) action))
)
(define-method (iterate (items jsint.Pair) action)
(let loop ((items items))
(if (pair? items)
(begin
(action (car items))
(loop (cdr items))))))
(define-method (iterate (items Object[]) action)
(let loop ((i 0)
(L (vector-length items)))
(if (< i L) (begin (action (vector-ref items i)) (loop (+ i 1) L)))))
(define-method (iterate (items String) action)
(let loop ((i 0)
(L (string-length items)))
(if (< i L) (begin (action (string-ref items i)) (loop (+ i 1) L)))))
(define-method (iterate (items Object) action)
(if (.isArray (.getClass items))
(let loop ((i 0)
(L (java.lang.reflect.Array.getLength items)))
(if (< i L)
(begin (action (java.lang.reflect.Array.get items i))
(loop (+ i 1) L))))
(error "Don't know how to iterate over " items)))
(define-method (iterate (items java.io.BufferedReader) action)
;; Iterate over the lines of a buffered reader.
(let loop ((it (.readLine items)))
(if (not (eq? it #null))
(begin
(action it)
(loop (.readLine items))))))
(define-method (iterate (items javax.swing.text.ElementIterator) action)
;; Unfortunately, this Class is not an iterator!
(let loop ((item (.next items)))
(if (not (isNull item))
(begin (action item)
(loop (.next items))))))
(define (map* f xs)
;; Like map but works for any container that iterate works on.
;; KRA 13MAY00: +++ Someday rewrite without reverse.
(let ((results '()))
(iterate xs (lambda (x) (set! results (cons (f x) results))))
(reverse results)))
(define (for-each* f xs)
;;; Like for-each but generalized for any container that iterate works on.
(iterate xs f))
;;;
;;; Fold to the left.
;;;
(define (foldL xs how so-far)
(if (isNull xs) so-far
(begin
(iterate xs (lambda (x) (set! so-far (how x so-far))))
so-far)))
(define identity (lambda (x) x))
(define (keep test)
(lambda (it sofar)
(if (test it) (cons it sofar) sofar)))
(define (find p xs)
;; Find first x of xs satisfying (p x).
(call/cc (lambda (return)
(iterate xs (lambda (x) (if (p x) (return x)))))))
(assert (= (find odd? '(2 4 6 3 5)) 3))
(assert (= (find odd? #(2 4 6 3 5)) 3))
;;; KRA 23JUL04: filter-in is deprecated. Use filter.
(define (filter-in p xs) (foldL xs (keep p) '()))
(assert (equal? (filter-in identity #null) '()))
(assert
(equal? (filter-in symbol? '(3 + x f define))
'(define f x +)))
;;; KRA 21APR02: filter-in reverses the list of kept things.
;;; (filter) keeps items in their original order.
(define (filter keep? xs) (reverse (filter-in keep? xs)))
(define (some p xs)
(call/cc (lambda (return)
(iterate xs (lambda (x) (if (p x) (return #t))))
#f)))
(define (every p xs)
(call/cc (lambda (return)
(iterate xs (lambda (x) (if (not (p x)) (return #f))))
#t)))
(define (crack string by)
(map* identity (StringTokenizer. string by)))
(assert (equal? (crack "foo/bar/baz" "/") '("foo" "bar" "baz")))
(define (separate by items)
;; (separate "," '(1 2 3)) -> (1 "," 2 "," 3)
(define (separate0 head tail)
(if (null? tail) (list head)
(cons head (cons by (separate0 (car tail) (cdr tail))))))
(if (null? items) items
(separate0 (car items) (cdr items))))
(assert (equal? (separate "," '(1 2 3)) '(1 "," 2 "," 3)))
(assert (equal? (separate "," (crack "foo/bar/baz" "/"))
'("foo" "," "bar" "," "baz")))
(define flatten
;; Flatten a list of lists into a list of atoms. Tail recursive version.
;; Can we cons less than this?
;; Can we use foldL?
(let () ; Lambda lift.
(define (flatten1 result xs)
(if (null? xs) (reverse result)
(let ((head (car xs))
(xs (cdr xs)))
(cond ((null? head) (flatten1 result xs))
((pair? head)
(flatten1 result (cons (car head) (cons (cdr head) xs))))
(else (flatten1 (cons head result) xs))))))
(lambda (xs) (flatten1 '() xs))))