source: project/release/5/srfi-41/trunk/streams-utils.scm @ 39713

Last change on this file since 39713 was 39713, checked in by Kon Lovett, 2 months ago

remove "primitives", replace inline type checks

File size: 10.7 KB
Line 
1;;;; streams-utils.scm
2;;;; Kon Lovett, Feb '19
3;;;; Kon Lovett, Apr '09
4
5; Copyright (C) 2007 by Philip L. Bewig of Saint Louis, Missouri, USA.  All rights
6; reserved.  Permission is hereby granted, free of charge, to any person obtaining a copy of
7; this software and associated documentation files (the "Software"), to deal in the Software
8; without restriction, including without limitation the rights to use, copy, modify, merge,
9; publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to
10; whom the Software is furnished to do so, subject to the following conditions: The above
11; copyright notice and this permission notice shall be included in all copies or substantial
12; portions of the Software.  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
14; FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
15; HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
16; CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
17; THE USE OR OTHER DEALINGS IN THE SOFTWARE.
18
19(module streams-utils
20
21(;export
22  stream-intersperse
23  stream-permutations
24  file->stream
25  stream-split
26  stream-unique
27  stream-fold-one
28  stream-member
29  stream-merge
30  stream-partition
31  stream-finds
32  stream-find
33  stream-remove
34  stream-every
35  stream-any
36  stream-and
37  stream-or
38  stream-fold-right
39  stream-fold-right-one
40  stream-assoc
41  stream-equal?
42  stream-quick-sort
43  stream-insertion-sort
44  stream-merge-sort
45  stream-maximum
46  stream-minimum
47  binary-tree-same-fringe?)
48
49(import scheme
50  (chicken base)
51  (chicken type)
52  (chicken syntax)
53  (only type-checks
54    check-list check-procedure
55    check-string check-natural-integer)
56  streams)
57
58;;;
59
60(define-inline (%check-streams loc strms #!optional argnam)
61  (when (null? strms) (error loc "no stream arguments" strms))
62  (for-each (cut check-stream loc <> argnam) strms)
63  strms )
64
65;(append xs args) = (reverse (append (reverse args) (reverse xs)))
66(define (right-section fn . args) (lambda xs (apply fn (append xs args))))
67
68;;;
69
70(define-stream (stream-intersperse yy x)
71  (stream-match (check-stream 'stream-intersperse yy 'stream)
72    (()
73      (stream (stream x)) )
74    ((y . ys)
75      (stream-append
76        (stream (stream-cons x yy))
77        (stream-map (lambda (z) (stream-cons y z)) (stream-intersperse ys x))) ) ) )
78
79(define-stream (stream-permutations xs)
80  (if (stream-null? (check-stream 'stream-permutations xs 'stream))
81    (stream (stream))
82    (stream-concat
83      (stream-map
84        (right-section stream-intersperse (stream-car xs))
85        (stream-permutations (stream-cdr xs)))) ) )
86
87(define-stream (file->stream filename #!optional (reader read-char))
88  (check-procedure 'file->streams reader 'reader)
89  (let ((port (open-input-file (check-string 'file->streams filename 'filename))))
90    (stream-let loop ((item (reader port)))
91      (if (eof-object? item)
92        (begin (close-input-port port) stream-null)
93        (stream-cons item (loop (reader port))) ) ) ) )
94
95(define (stream-split count strm)
96  (check-stream 'stream-split strm 'stream)
97  (check-natural-integer 'stream-split count 'count)
98  (values (stream-take count strm) (stream-drop count strm)))
99
100(define-stream (stream-unique eql? strm)
101  (check-procedure 'stream-unique eql? 'equivalence)
102  (stream-let loop ((strm (check-stream 'stream-unique strm 'stream)))
103    (if (stream-null? strm)
104      stream-null
105      (stream-cons
106        (stream-car strm)
107        (loop (stream-drop-while (lambda (x) (eql? (stream-car strm) x)) strm))) ) ) )
108
109(define (stream-fold-one func strm)
110  (check-stream 'stream-fold-one strm 'stream)
111  (stream-fold
112    (check-procedure 'stream-fold-one func 'function)
113    (stream-car strm)
114    (stream-cdr strm)) )
115
116(define-stream (stream-member eql? item strm)
117  (check-procedure 'stream-member eql? 'equivalence)
118  (stream-let loop ((strm (check-stream 'stream-member strm 'stream)))
119    (cond
120      ((stream-null? strm)
121        #f)
122      ((eql? item (stream-car strm))
123        strm)
124      (else
125        (loop (stream-cdr strm)) ) ) ) )
126
127(define-stream (stream-merge lt? . strms)
128  ;
129  (define-stream (stream-merge$ xx yy)
130    (stream-match xx
131      (()
132        yy )
133      ((x . xs)
134        (stream-match yy
135          (() xx )
136          ((y . ys)
137            (if (lt? y x) (stream-cons y (stream-merge$ xx ys))
138              (stream-cons x (stream-merge$ xs yy))))) ) ) )
139  ;
140  (check-procedure 'stream-merge lt? 'less-than)
141  (stream-let loop ((strms (%check-streams 'stream-merge strms 'stream)))
142    (cond
143      ((null? strms)
144        stream-null )
145      ((null? (cdr strms))
146        (car strms) )
147      (else
148        (stream-merge$ (car strms) (apply stream-merge lt? (cdr strms))) ) ) ) )
149
150(define (stream-partition pred? strm)
151  (check-procedure 'stream-partition pred? 'predicate)
152  (stream-unfolds
153    (lambda (s)
154      (if (stream-null? s) (values s '() '())
155        (let ((a (stream-car s))
156              (d (stream-cdr s)))
157          (if (pred? a)
158            (values d (list a) #f)
159            (values d #f (list a)) ) ) ) )
160    (check-stream 'stream-partition strm 'stream)) )
161
162(define-stream (stream-finds eql? item strm)
163  (check-procedure 'stream-finds eql? 'equivalence)
164  (stream-of
165    (car x)
166    (x in (stream-zip (stream-from 0) (check-stream 'stream-finds strm 'stream)))
167    (eql? item (cadr x))) )
168
169(define (stream-find eql? item strm)
170  (check-stream 'stream-find strm 'stream)
171  (check-procedure 'stream-find eql? 'equivalence)
172  (stream-car (stream-append (stream-finds eql? item strm) (stream #f))) )
173
174(define-stream (stream-remove pred? strm)
175  (check-procedure 'stream-remove pred? 'predicate)
176  (stream-filter (complement pred?) (check-stream 'stream-remove strm 'stream)) )
177
178(define (stream-every pred? strm)
179  (check-procedure 'stream-every pred? 'predicate)
180  (let loop ((strm (check-stream 'stream-every strm 'stream)))
181    (cond
182      ((stream-null? strm)
183        #t )
184      ((not (pred? (stream-car strm)))
185        #f )
186      (else
187        (loop (stream-cdr strm)) ) ) ) )
188
189(define (stream-any pred? strm)
190  (check-procedure 'stream-any pred? 'predicate)
191  (let loop ((strm (check-stream 'stream-any strm 'stream)))
192    (cond
193      ((stream-null? strm)
194        #f )
195      ((pred? (stream-car strm))
196        #t )
197      (else
198        (loop (stream-cdr strm)) ) ) ) )
199
200(define (stream-and strm)
201  (let loop ((strm (check-stream 'stream-and strm 'stream)))
202    (cond
203      ((stream-null? strm)
204        #t )
205      ((not (stream-car strm))
206        #f )
207      (else
208        (loop (stream-cdr strm)) ) ) ) )
209
210(define (stream-or strm)
211  (check-stream 'stream-or strm 'stream)
212  (let loop ((strm strm))
213    (cond
214      ((stream-null? strm)
215        #f )
216      ((stream-car strm)
217        #t )
218      (else
219        (loop (stream-cdr strm)) ) ) ) )
220
221(define (stream-fold-right func base strm)
222  (check-procedure 'stream-fold-right func 'function)
223  (let loop ((strm (check-stream 'stream-fold-right strm 'stream)))
224    (if (stream-null? strm)
225      base
226      (func (stream-car strm) (loop (stream-cdr strm))) ) ) )
227
228(define (stream-fold-right-one func strm)
229  (check-procedure 'stream-fold-right-one func 'function)
230  (let loop ((strm (check-stream 'stream-fold-right-one strm 'stream)))
231    (stream-match strm
232      ((x) x )
233      ((x . xs) (func x (loop xs)) ) ) ) )
234
235(define (stream-assoc key dict #!optional (eql? equal?))
236  (check-procedure 'stream-assoc eql? 'equivalence)
237  (let loop ((dict (check-stream 'stream-assoc dict 'stream)))
238    (cond
239      ((stream-null? dict)
240        #f )
241      ((eql? key (car (stream-car dict)))
242        (stream-car dict) )
243      (else
244        (loop (stream-cdr dict)) ) ) ) )
245
246; May never return
247(define (stream-equal? eql? xs ys)
248  (let loop ((xs (check-stream 'stream-equal? xs 'stream1))
249             (ys (check-stream 'stream-equal? ys 'stream2)))
250    (cond
251      ((and (stream-null? xs) (stream-null? ys))
252        #t )
253      ((or (stream-null? xs) (stream-null? ys))
254        #f )
255      ((not (eql? (stream-car xs) (stream-car ys)))
256        #f )
257      (else
258        (loop (stream-cdr xs) (stream-cdr ys)) ) ) ) )
259
260(define-stream (stream-quick-sort lt? strm)
261  (check-procedure 'stream-quick-sort lt? 'less-than)
262  (let loop ((strm (check-stream 'stream-quick-sort strm 'stream)))
263    (if (stream-null? strm)
264      stream-null
265      (let ((x (stream-car strm))
266            (xs (stream-cdr strm)))
267        (stream-append
268          (loop (stream-filter (lambda (u) (lt? u x)) xs))
269          (stream x)
270          (loop (stream-filter (lambda (u) (not (lt? u x))) xs))) ) ) ) )
271
272(define-stream (stream-insertion-sort lt? strm)
273  ;
274  (define-stream (insert$ strm x)
275    (stream-match strm
276      (()
277        (stream x) )
278      ((y . ys)
279        (if (lt? y x) (stream-cons y (insert$ ys x))
280          (stream-cons x strm) ) ) ) )
281  ;
282  (check-procedure 'stream-insertion-sort lt? 'less-than)
283  (stream-fold insert$ stream-null (check-stream 'stream-insertion-sort strm 'stream)) )
284
285(define-stream (stream-merge-sort lt? strm)
286  (check-procedure 'stream-merge-sort lt? 'less-than)
287  (let loop ((strm (check-stream 'stream-merge-sort strm 'stream)))
288    (let ((n (quotient (stream-length strm) 2)))
289      (if (zero? n)
290        strm
291        (stream-merge lt? (loop (stream-take n strm)) (loop (stream-drop n strm))) ) ) ) )
292
293(define (stream-maximum lt? strm)
294  (check-procedure 'stream-maximum lt? 'less-than)
295  (stream-fold-one
296    (lambda (x y) (if (lt? x y) y x))
297    (check-stream 'stream-maximum strm 'stream)) )
298
299(define (stream-minimum lt? strm)
300  (check-procedure 'stream-minimum lt? 'less-than)
301  (stream-fold-one
302    (lambda (x y) (if (lt? x y) x y))
303    (check-stream 'stream-minimum strm 'stream)) )
304
305;; Lazy binary-tree "same fringe"
306
307(define (binary-tree-same-fringe? tree1 tree2 #!optional (eql? equal?))
308  ;
309  (define-stream (flatten tree)
310    (cond
311      ((null? tree)
312        stream-null )
313      ((pair? (car tree) )
314        (stream-append (flatten (car tree)) (flatten (cdr tree))))
315      (else
316        (stream-cons (car tree) (flatten (cdr tree))) ) ) )
317  ;
318  (let loop ((t1 (flatten (check-list 'same-fringe? tree1 'tree1)))
319             (t2 (flatten (check-list 'same-fringe? tree2 'tree2))))
320    (cond
321      ((and (stream-null? t1) (stream-null? t2))
322        #t )
323      ((or  (stream-null? t1) (stream-null? t2))
324        #f )
325      ((not (eql? (stream-car t1) (stream-car t2)))
326        #f )
327      (else
328        (loop (stream-cdr t1) (stream-cdr t2)) ) ) ) )
329
330) ;module streams-utils
Note: See TracBrowser for help on using the repository browser.