source: project/release/4/srfi-41/trunk/streams-utils.scm @ 14609

Last change on this file since 14609 was 14609, checked in by Kon Lovett, 11 years ago

Better errmsg (the original) for nary stream procs.

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