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

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

remove "primitives"

File size: 10.8 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  streams
54  (only type-errors
55    error-list error-procedure
56    error-string error-natural-integer))
57
58(define-inline (%structure-instance? x s) (##core#inline "C_i_structurep" x s))
59
60(include-relative "inline-type-checks")
61
62(include-relative "streams-inlines")
63
64;;;
65
66;(append xs args) = (reverse (append (reverse args) (reverse xs)))
67(define (right-section fn . args) (lambda xs (apply fn (append xs args))))
68
69;;;
70
71(define-stream (stream-intersperse yy x)
72  (stream-match (%check-stream 'stream-intersperse yy 'stream)
73    (()
74      (stream (stream x)) )
75    ((y . ys)
76      (stream-append
77        (stream (stream-cons x yy))
78        (stream-map (lambda (z) (stream-cons y z)) (stream-intersperse ys x))) ) ) )
79
80(define-stream (stream-permutations xs)
81  (if (stream-null? (%check-stream 'stream-permutations xs 'stream))
82    (stream (stream))
83    (stream-concat
84      (stream-map
85        (right-section stream-intersperse (stream-car xs))
86        (stream-permutations (stream-cdr xs)))) ) )
87
88(define-stream (file->stream filename #!optional (reader read-char))
89  (%check-procedure 'file->streams reader 'reader)
90  (let ((port (open-input-file (%check-string 'file->streams filename 'filename))))
91    (stream-let loop ((item (reader port)))
92      (if (eof-object? item)
93        (begin (close-input-port port) stream-null)
94        (stream-cons item (loop (reader port))) ) ) ) )
95
96(define (stream-split count strm)
97  (%check-stream 'stream-split strm 'stream)
98  (%check-natural-integer 'stream-split count 'count)
99  (values (stream-take count strm) (stream-drop count strm)))
100
101(define-stream (stream-unique eql? strm)
102  (%check-procedure 'stream-unique eql? 'equivalence)
103  (stream-let loop ((strm (%check-stream 'stream-unique strm 'stream)))
104    (if (stream-null? strm)
105      stream-null
106      (stream-cons
107        (stream-car strm)
108        (loop (stream-drop-while (lambda (x) (eql? (stream-car strm) x)) strm))) ) ) )
109
110(define (stream-fold-one func strm)
111  (%check-stream 'stream-fold-one strm 'stream)
112  (stream-fold
113    (%check-procedure 'stream-fold-one func 'function)
114    (stream-car strm)
115    (stream-cdr strm)) )
116
117(define-stream (stream-member eql? item strm)
118  (%check-procedure 'stream-member eql? 'equivalence)
119  (stream-let loop ((strm (%check-stream 'stream-member strm 'stream)))
120    (cond
121      ((stream-null? strm)
122        #f)
123      ((eql? item (stream-car strm))
124        strm)
125      (else
126        (loop (stream-cdr strm)) ) ) ) )
127
128(define-stream (stream-merge lt? . strms)
129  ;
130  (define-stream (stream-merge$ xx yy)
131    (stream-match xx
132      (()
133        yy )
134      ((x . xs)
135        (stream-match yy
136          (() xx )
137          ((y . ys)
138            (if (lt? y x) (stream-cons y (stream-merge$ xx ys))
139              (stream-cons x (stream-merge$ xs yy))))) ) ) )
140  ;
141  (%check-procedure 'stream-merge lt? 'less-than)
142  (stream-let loop ((strms (%check-streams 'stream-merge strms 'stream)))
143    (cond
144      ((null? strms)
145        stream-null )
146      ((null? (cdr strms))
147        (car strms) )
148      (else
149        (stream-merge$ (car strms) (apply stream-merge lt? (cdr strms))) ) ) ) )
150
151(define (stream-partition pred? strm)
152  (%check-procedure 'stream-partition pred? 'predicate)
153  (stream-unfolds
154    (lambda (s)
155      (if (stream-null? s) (values s '() '())
156        (let ((a (stream-car s))
157              (d (stream-cdr s)))
158          (if (pred? a)
159            (values d (list a) #f)
160            (values d #f (list a)) ) ) ) )
161    (%check-stream 'stream-partition strm 'stream)) )
162
163(define-stream (stream-finds eql? item strm)
164  (%check-procedure 'stream-finds eql? 'equivalence)
165  (stream-of
166    (car x)
167    (x in (stream-zip (stream-from 0) (%check-stream 'stream-finds strm 'stream)))
168    (eql? item (cadr x))) )
169
170(define (stream-find eql? item strm)
171  (%check-stream 'stream-find strm 'stream)
172  (%check-procedure 'stream-find eql? 'equivalence)
173  (stream-car (stream-append (stream-finds eql? item strm) (stream #f))) )
174
175(define-stream (stream-remove pred? strm)
176  (%check-procedure 'stream-remove pred? 'predicate)
177  (stream-filter (complement pred?) (%check-stream 'stream-remove strm 'stream)) )
178
179(define (stream-every pred? strm)
180  (%check-procedure 'stream-every pred? 'predicate)
181  (let loop ((strm (%check-stream 'stream-every strm 'stream)))
182    (cond
183      ((stream-null? strm)
184        #t )
185      ((not (pred? (stream-car strm)))
186        #f )
187      (else
188        (loop (stream-cdr strm)) ) ) ) )
189
190(define (stream-any pred? strm)
191  (%check-procedure 'stream-any pred? 'predicate)
192  (let loop ((strm (%check-stream 'stream-any strm 'stream)))
193    (cond
194      ((stream-null? strm)
195        #f )
196      ((pred? (stream-car strm))
197        #t )
198      (else
199        (loop (stream-cdr strm)) ) ) ) )
200
201(define (stream-and strm)
202  (let loop ((strm (%check-stream 'stream-and strm 'stream)))
203    (cond
204      ((stream-null? strm)
205        #t )
206      ((not (stream-car strm))
207        #f )
208      (else
209        (loop (stream-cdr strm)) ) ) ) )
210
211(define (stream-or strm)
212  (%check-stream 'stream-or strm 'stream)
213  (let loop ((strm strm))
214    (cond
215      ((stream-null? strm)
216        #f )
217      ((stream-car strm)
218        #t )
219      (else
220        (loop (stream-cdr strm)) ) ) ) )
221
222(define (stream-fold-right func base strm)
223  (%check-procedure 'stream-fold-right func 'function)
224  (let loop ((strm (%check-stream 'stream-fold-right strm 'stream)))
225    (if (stream-null? strm)
226      base
227      (func (stream-car strm) (loop (stream-cdr strm))) ) ) )
228
229(define (stream-fold-right-one func strm)
230  (%check-procedure 'stream-fold-right-one func 'function)
231  (let loop ((strm (%check-stream 'stream-fold-right-one strm 'stream)))
232    (stream-match strm
233      ((x) x )
234      ((x . xs) (func x (loop xs)) ) ) ) )
235
236(define (stream-assoc key dict #!optional (eql? equal?))
237  (%check-procedure 'stream-assoc eql? 'equivalence)
238  (let loop ((dict (%check-stream 'stream-assoc dict 'stream)))
239    (cond
240      ((stream-null? dict)
241        #f )
242      ((eql? key (car (stream-car dict)))
243        (stream-car dict) )
244      (else
245        (loop (stream-cdr dict)) ) ) ) )
246
247; May never return
248(define (stream-equal? eql? xs ys)
249  (let loop ((xs (%check-stream 'stream-equal? xs 'stream1))
250             (ys (%check-stream 'stream-equal? ys 'stream2)))
251    (cond
252      ((and (stream-null? xs) (stream-null? ys))
253        #t )
254      ((or (stream-null? xs) (stream-null? ys))
255        #f )
256      ((not (eql? (stream-car xs) (stream-car ys)))
257        #f )
258      (else
259        (loop (stream-cdr xs) (stream-cdr ys)) ) ) ) )
260
261(define-stream (stream-quick-sort lt? strm)
262  (%check-procedure 'stream-quick-sort lt? 'less-than)
263  (let loop ((strm (%check-stream 'stream-quick-sort strm 'stream)))
264    (if (stream-null? strm)
265      stream-null
266      (let ((x (stream-car strm))
267            (xs (stream-cdr strm)))
268        (stream-append
269          (loop (stream-filter (lambda (u) (lt? u x)) xs))
270          (stream x)
271          (loop (stream-filter (lambda (u) (not (lt? u x))) xs))) ) ) ) )
272
273(define-stream (stream-insertion-sort lt? strm)
274  ;
275  (define-stream (insert$ strm x)
276    (stream-match strm
277      (()
278        (stream x) )
279      ((y . ys)
280        (if (lt? y x) (stream-cons y (insert$ ys x))
281          (stream-cons x strm) ) ) ) )
282  ;
283  (%check-procedure 'stream-insertion-sort lt? 'less-than)
284  (stream-fold insert$ stream-null (%check-stream 'stream-insertion-sort strm 'stream)) )
285
286(define-stream (stream-merge-sort lt? strm)
287  (%check-procedure 'stream-merge-sort lt? 'less-than)
288  (let loop ((strm (%check-stream 'stream-merge-sort strm 'stream)))
289    (let ((n (quotient (stream-length strm) 2)))
290      (if (zero? n)
291        strm
292        (stream-merge lt? (loop (stream-take n strm)) (loop (stream-drop n strm))) ) ) ) )
293
294(define (stream-maximum lt? strm)
295  (%check-procedure 'stream-maximum lt? 'less-than)
296  (stream-fold-one
297    (lambda (x y) (if (lt? x y) y x))
298    (%check-stream 'stream-maximum strm 'stream)) )
299
300(define (stream-minimum lt? strm)
301  (%check-procedure 'stream-minimum lt? 'less-than)
302  (stream-fold-one
303    (lambda (x y) (if (lt? x y) x y))
304    (%check-stream 'stream-minimum strm 'stream)) )
305
306;; Lazy binary-tree "same fringe"
307
308(define (binary-tree-same-fringe? tree1 tree2 #!optional (eql? equal?))
309  ;
310  (define-stream (flatten tree)
311    (cond
312      ((null? tree)
313        stream-null )
314      ((pair? (car tree) )
315        (stream-append (flatten (car tree)) (flatten (cdr tree))))
316      (else
317        (stream-cons (car tree) (flatten (cdr tree))) ) ) )
318  ;
319  (let loop ((t1 (flatten (%check-list 'same-fringe? tree1 'tree1)))
320             (t2 (flatten (%check-list 'same-fringe? tree2 'tree2))))
321    (cond
322      ((and (stream-null? t1) (stream-null? t2))
323        #t )
324      ((or  (stream-null? t1) (stream-null? t2))
325        #f )
326      ((not (eql? (stream-car t1) (stream-car t2)))
327        #f )
328      (else
329        (loop (stream-cdr t1) (stream-cdr t2)) ) ) ) )
330
331) ;module streams-utils
Note: See TracBrowser for help on using the repository browser.