source: project/wiki/stream-ext @ 8530

Last change on this file since 8530 was 8530, checked in by azul, 13 years ago

Tweaks

File size: 29.4 KB
Line 
1[[toc:]]
2[[tags:eggs streams]]
3
4== Introduction
5
6The stream-ext egg provides many convenient extensions to work with [[srfi:40]] streams.
7
8== Author
9
10This egg is made by [[http://azul.freaks-unidos.net/|Alejandro Forero Cuervo]] <azul@freaks-unidos.net>.
11
12== Requires
13
14* [[srfi-40]]
15* [[format-modular]]
16
17== License
18
19The stream-ext egg for Chicken Scheme is in the public domain and may be reproduced or copied without
20permission from its author.  Citation of the source is appreciated.
21
22== Constructors
23
24<procedure name="stream-xcons" args="a b" returns="stream">
25Of utility only as a value to be conveniently passed to higher-order procedures.
26
27<examples>
28<expr>(stream-xcons (stream 'b 'c) 'a)</expr>
29<result>#<stream (a b c)></result>
30<expr>(stream-xcons (stream 2 3 4) 1)</expr>
31<result>#<stream 1 2 3 4></result>
32</examples>
33
34The name stands for "eXchanged CONS."
35</procedure>
36
37<procedure name="stream-cons*" returns="stream" args="a b">
38
39Like {{stream}}, but the last argument
40provides the tail of the constructed stream, returning:
41
42<enscript highlight=scheme>(stream-cons elt1 (stream-cons elt2 (stream-cons ... eltn)))</enscript>
43
44Examples:
45
46<enscript highlight=scheme>(stream-cons* 1 2 3 (stream 4))
47=> #<stream (1 2 3 4)>
48(stream-cons* (stream 4))
49=> #<stream (4)></enscript>
50</procedure>
51
52=== make-stream
53
54 [procedure] (make-stream n [fill])
55
56Returns an {{n}}-element stream, whose elements
57are all the value {{fill}}.
58If the {{fill}} argument is not given,
59the elements of the stream may be arbitrary values.
60
61<enscript highlight=scheme>(make-stream 4 'c)
62=> <stream (c c c c)></enscript>
63
64=== stream-tabulate
65
66 [procedure] (stream-tabulate n init-proc)
67
68Returns an {{n}}-element list.
69Element {{i}} of the list, where 0 <= {{i}} < {{n}},
70is produced by {{(init-proc i)}}.
71
72<enscript highlight=scheme>(stream-tabulate 4 identity)
73=> #<stream (0 1 2 3)></enscript>
74
75=== stream-iota
76
77 [procedure] (stream-iota a b)
78
79Returns a list containing the elements:
80
81<enscript highlight=scheme>(start start+step ... start+(count-1)*step)</enscript>
82
83The {{start}} and {{step}} parameters default
84to {{0}} and {{1}}, respectively.
85This procedure takes its name from the APL primitive.
86
87<enscript highlight=scheme>(stream-iota 5)
88=> #<stream (0 1 2 3 4)>
89(stream-iota 5 0 -0.1)
90=> #<stream (0 -0.1 -0.2 -0.3 -0.4)></enscript>
91
92=== stream-format
93
94 [procedure] (stream-format fmt ...)
95
96Does the same as {{(format #f fmt ...)}},
97but returns the result as a stream of characters rather than a string.
98
99=== stream-lines
100
101 [procedure] (stream-lines str)
102
103Returns a stream with the lines found in the stream of
104characters {{str}}.  Each line is itself returned
105as a stream of characters.  It is an error if {{str}} contains
106elements that are not characters.
107
108<enscript highlight=scheme>(stream-lines (stream #\h #\e #\y #\newline #\y #\o #\u))
109=> #<stream (#<stream (#\h #\e #\y)> #<stream (#\y #\o #\u)>)></enscript>
110
111== Conversion
112
113=== stream->list
114
115 [procedure] (stream->list str)
116
117Returns a list with the elements in stream {{str}}.
118It is an error to pass an infinite stream.
119
120=== list->stream
121
122 [procedure] (list->stream list)
123
124Returns a stream with the elements in list {{list}}.
125The list might be circular (infinite), in which case the resulting
126stream will be infinite as well.
127
128=== stream->string
129
130 [procedure] (stream->string str)
131
132Returns a string with its characters read from
133the stream {{str}}.
134It is an error if {{str}} does not end or if it
135has elements than are not characters.
136
137This function is the inverse of {{string->stream}}.
138
139=== string->stream
140
141 [procedure] (string->stream str)
142
143Returns a finite stream with the characters
144in the string {{str}}.
145
146This function is the inverse of {{stream->string}}.
147
148=== number->stream
149
150 [procedure] (number->stream str)
151
152...
153
154=== stream->number
155
156 [procedure] (stream->number str)
157
158...
159
160=== port->stream
161
162 [procedure] (port->stream [in [reader [close-at-eof]]])
163
164Returns a stream with the contents of the input port {{in}},
165which defaults to the current input port.
166
167{{reader}} is a procedure.  When called, it should read
168and return one element from the port passed as its only argument, advancing the
169read pointer (or return the eof object when no more elements
170are available in the port).  The default value is {{read-char}},
171which results in a stream of characters, but {{read}} and
172{{read-line}} can also be specified.
173
174TODO: Documment close-at-eof.
175
176=== iterator->stream
177
178 [procedure] (iterator->stream proc)
179
180Turns an iterator into a stream.  {{proc}} should be
181a procedure of two arguments.  The first is a one-argument
182procedure that collects objects (adds them to an enumeration)
183and the second is a procedure of no arguments that can be used
184to stop iteration prematurely.
185
186{{iterator->stream}} returns a stream.  The
187iterator {{proc}} is only allowed to run as objects
188are read from the stream (with {{stream-car}} or
189{{stream-cdr}}).
190
191Example:
192
193<enscript highlight=scheme>(define (list->stream alist)
194  (iterator->stream
195    (lambda (collect stop)
196      (for-each collect alist))))</enscript>
197
198== Input and output
199
200=== with-output-to-stream
201
202 [procedure] (with-output-to-stream proc)
203
204Returns a stream of characters, which is built by calling
205{{proc}}, a procedure of no arguments, with its output
206port bound to a custom port.  As characters are read from the
207stream (by {{stream-car}} or {{stream-cdr}}),
208{{proc}} is allowed to execute until
209it writes as many characters as required.  For example,
210if the stream returned is immediately discarded, {{proc}}
211will not called at all.
212
213<enscript highlight=scheme>(with-output-to-stream
214  (lambda ()
215    (format #t "Hey!~%")))
216=> #<stream (#\H #\e #\y #\! #\newline)></enscript>
217
218Remember that {{proc}} is only executed gradually,
219as the values from the stream are required.  As a consequence,
220certain problems could arise by uncareful use of non-reentrant
221functions.
222
223=== write-stream
224
225 [procedure] (write-stream stream [port [writer]])
226
227Write all the elements in the stream {{stream}} to the output port {{port}},
228which defaults to the current output port.
229If the stream is infinite, this function does not return.
230
231{{writer}} is the procedure used to write individual
232elements to the port.  It should receive the element to be written
233and the output port as its only arguments.  The default value is {{write-char}}
234but {{write}} and {{write-line}} can also be used (depending
235on the contents of {{stream}}).
236
237== Predicates
238
239=== stream=
240
241 [procedure] (stream= elt= str1 ...)
242
243Determines stream equality, given an element-equality procedure.
244Stream {{A}} equals stream {{B}} if they are of the
245same length, and their corresponding elements are equal, as determined
246by {{elt=}}.
247If the element-comparison procedure's first argument is from stri,
248then its second argument is from stri+1, i.e. it is always called
249as {{(elt= a b)}} for {{a}} an element of stream {{A}},
250and {{b}} an element of stream {{B}}.
251
252In the n-ary case, every {{stri}} is compared to {{stri+1}}
253(as opposed, for example, to comparing {{str1}} to every {{stri}},
254for {{i}} > 1).
255If there are no list arguments at all, {{stream=}} simply returns true.
256
257The dynamic order in which the {{elt=}} procedure is applied to pairs of
258elements is not specified. For example, if {{stream=}} is applied to three lists,
259{{A}}, {{B}},
260and {{C}}, it may first completely compare
261{{A}} to {{B}},
262then compare {{B}} to {{C}}, or it may
263compare the first elements of {{A}} and {{B}},
264then the first elements of {{B}} and {{C}},
265then the second elements of {{A}} and {{B}}, and so forth.
266
267The equality procedure must be consistent with {{eq?}}.
268That is, it must be the case that:
269
270<enscript highlight=scheme>(eq? x y) => (elt= x y)</enscript>
271
272This implies that two lists which are {{eq?}} are always {{stream=}}
273as well; implementations may exploit this fact to "short-cut" the element-by-element comparisons.
274
275<enscript highlight=scheme>(stream= eq?)
276=> #t       ; Trivial cases
277(stream= eq? (stream 0 1 2))
278=> #t</enscript>
279
280=== stream-prefix=
281
282 [procedure] (stream-prefix= str prefix [=])
283
284Evaluates whether the elements at the beginning of stream
285{{str}} are equal to the elements in the list
286{{prefix}}.
287
288{{eq}} is the function used to compare the individual elements.
289The default is {{equal?}}.
290
291If the prefix of the stream matches {{prefix}}, the
292function returns the contents of {{stream}} following
293it.  False is returned otherwise.
294
295<enscript highlight=scheme>(stream-prefix= (stream 1 2 3 4) '(1 2))
296=> #<stream (3 4)>
297(stream-prefix= (stream 1 2 3 4) '(1 3))
298=> #f</enscript>
299
300== Selectors
301
302=== stream-caar ... stream-cddddr
303
304 [procedure] (stream-caar pair)
305 [procedure] (stream-cadr pair)
306 :
307 [procedure] (stream-cdddar pair)
308 [procedure] (stream-cddddr pair)
309
310These procedures are compositions of
311{{stream-car}} and {{stream-cdr}},
312where for example {{stream-caddr}} could be defined by:
313
314<enscript highlight=scheme>(define (stream-caddr x) (stream-car (stream-cdr (stream-cdr x))))</enscript>
315
316Arbitrary compositions, up to four deep, are provided.
317There are twenty-eight of these procedures in all.
318
319=== stream-ref
320
321 [procedure] (stream-ref str pos)
322
323Returns the element in the stream {{str}} at the
324position {{pos}}.  This is the same as the stream-car
325of {{(stream-drop str pos)}}. It is an error if
326{{str}} has {{pos}} or fewer elements.
327
328<enscript highlight=scheme>(stream-ref (stream 0 1 2 3 4 5) 3)
329=> 3</enscript>
330
331=== stream-first ... stream-tenth
332
333 [procedure] (stream-first str)
334 [procedure] (stream-second str)
335 :
336 [procedure] (stream-ninth str)
337 [procedure] (stream-tenth str)
338
339Synonyms for {{(stream-car str)}},
340{{(stream-cadr str)}}, {{(stream-caddr str)}}, ...
341
342<enscript highlight=scheme>(stream-third (stream 0 1 2 3 4))
343=> 2</enscript>
344
345=== stream-take
346
347 [procedure] (stream-take str count)
348
349Returns a stream with the first {{count}} elements
350in stream {{str}}.  It is an error if {{str}}
351has fewer than {{count}} elements.
352
353<enscript highlight=scheme>(stream-take (stream 1 2 3 4 5) 2)
354=> #<stream (1 2)></enscript>
355
356=== stream-drop
357
358 [procedure] (stream-drop str count)
359
360Returns the sub-stream of {{str}} obtained by omitting
361the first {{count}} elements. It is an error if list has
362fewer than {{count}} elements.
363
364<enscript highlight=scheme>(stream-drop (stream 0 1 2 3 4 5) 3)
365=> #<stream (3 4 5)></enscript>
366
367=== stream-intersperse
368
369 [procedure] (stream-intersperse stream element)
370
371Returns a new stream with the elements in the stream {{stream}}
372but placing {{element}} between each.
373
374<enscript highlight=scheme>(stream-intersperse (stream 0 1 2 3) #f)
375=> #<stream (0 #f 1 #f 2 #f 3)>
376(stream-intersperse (stream 0) 1)
377=> #<stream (0)></enscript>
378
379=== stream-split
380
381 [procedure] (stream-split str pred)
382
383Splits the stream {{str}} into multiple streams, removing
384the elements satisfying predicate {{pred}}.
385This is similar to what {{string-split}} does
386but operates on streams (rather than strings) and returns the result
387as a stream of streams (rather than a list of strings).
388
389Example:
390
391<enscript highlight=scheme>(stream-split (stream 1 2 3 5 7 8 9 10) even?)
392=> #<stream (#<stream (1)> #<stream (3 5 7)> #<stream (9)>)></enscript>
393
394=== stream-last
395
396 [procedure] (stream-last str)
397
398Returns the last element of the non-empty finite stream {{str}}.
399It is an error to pass an empty stream.
400
401<enscript highlight=scheme>(stream-last (stream 'a 'b 'c))
402=> c</enscript>
403
404{{stream-last}} can be defined as:
405
406<enscript highlight=scheme>(define (stream-last stream)
407  (stream-car (stream-last-n stream 1)))</enscript>
408
409=== stream-last-n
410
411[procedure] (stream-last-n stream count)
412
413Returns a stream with the last {{count}}
414elements of the finite stream {{str}}.  If fewer
415than {{count}} elements are available in {{stream}},
416{{stream}} itself is returned.
417
418<enscript highlight=scheme>(stream-null? (stream-last-n (stream #\a #\b #\c #\d) 0))
419=> #t
420(stream-last-n (stream #\a #\b #\c #\d) 1)
421=> #<stream (#\d)>
422(stream-last-n (stream #\a #\b #\c #\d) 3)
423=> #<stream (#\b #\c #\d)>
424(stream-last-n (stream #\a #\b #\c #\d) 20)
425=> #<stream (#\a #\b #\c #\d)></enscript>
426
427=== stream-butlast
428
429 [procedure] (stream-butlast stream)
430
431Returns a stream with all the elements in the
432non-empty stream {{str}} except the last.
433The order of the elements is respected.
434
435<enscript highlight=scheme>(stream-butlast (stream #\a #\b #\c))
436=> #<stream (#\a #\b)></enscript>
437
438{{stream-butlast}} can be defined as:
439
440<enscript highlight=scheme>(define (stream-butlast stream)
441  (stream-car (stream-butlast-n stream 1)))</enscript>
442
443=== stream-butlast-n
444
445 [procedure] (stream-butlast-n stream count)
446
447Returns a stream with all the elements in the
448stream {{stream}} except the last
449{{count}}.  The order of the elements is
450respected.  It is an error if {{stream}}
451has fewer than {{count}} elements.
452
453<enscript highlight=scheme>(stream-butlast-n (stream #\a #\b #\c) 2)
454=> #<stream (#\a)>
455(stream-null? (stream-butlast-n (stream #\a #\b #\c) 3))
456=> #t</enscript>
457
458== Miscellaneous: length, append, concatenate, reverse, zip & count
459
460=== stream-length
461
462 [procedure] (stream-length str)
463
464Returns the length of the argument stream (a non-negative integer n such that
465stream-cdr applied n times to the stream produces the null stream).
466
467This function does not return when {{str}} is an
468infinite streams.
469
470Returns the length of the stream {{str}}.
471This call does not return if {{str}} is an
472infinite stream.
473
474<enscript highlight=scheme>(stream-length (stream 0 1 2 3))
475=> 4</enscript>
476
477=== stream-length>=
478
479 [procedure] (stream-length>= str len)
480
481Returns {{#t}} if the length of the stream {{str}}
482is greater or equal than {{len}}, {{#f}} otherwise.
483
484For finite streams, this is equivalent, albeit faster, to:
485
486<enscript highlight=scheme>(>= (stream-length str) len)</enscript>
487
488However, for infinite streams it is equivalent to {{#t}}
489(whereas the above code would never terminate).
490
491=== stream-append
492
493 [procedure] (stream-append str1 str2 ...)
494
495{{stream-append}} returns a stream consisting of the elements of str1
496followed by the elements of the other stream parameters.
497
498<enscript highlight=scheme>(stream-append (stream 1) (stream 2))
499=> #<stream (1 2)>
500(stream-append (stream 1) (stream 2 3 4))
501=> #<stream (1 2 3 4)>
502(stream-append (stream 'a '(b)) (stream '(c)))
503=> #<stream (a (b) (c))></enscript>
504
505=== stream-concatenate
506
507 [procedure] (stream-concatenate str)
508
509...
510
511=== stream-reverse
512
513 [procedure] (stream-reverse str)
514
515{{stream-reverse}}
516returns a stream consisting of the elements of
517the stream {{str}} in reverse order.
518
519This procedure does not return if {{str}} is an infinite
520stream.
521
522<enscript highlight=scheme>(stream-reverse (stream 1 2 3))
523=> #<stream (3 2 1)>
524(stream-reverse (stream 'a '(b c) 'd '(e (f))))
525=> #<stream ((e (f)) d (b c) a)></enscript>
526
527=== stream-append-reverse
528
529 [procedure] (stream-append-reverse rev-head tail)
530
531{{stream-append-reverse}} returns
532{{(stream-append (stream-reverse rev-head) tail)}}.
533It is
534provided because it is a common operation -- a common list-processing style
535calls for this exact operation to transfer values accumulated in reverse order
536onto the front of another list, and because the implementation is significantly
537more efficient than the simple composition it replaces.
538
539This procedure does not return if {{rev-head}} is an infinite stream.
540
541=== stream-count
542
543 [procedure] (stream-count pred str1 str2 ...)
544
545{{pred}} is a procedure taking as many arguments as there are streams and
546returning a single value. It is applied element-wise to the elements of the
547streams, and a count is tallied of the number of elements that produce a true
548value. This count is returned. count is "iterative" in that it is guaranteed to
549apply {{pred}} to the stream elements in a left-to-right order. The counting stops
550when the shortest list expires.
551
552If all the streams are infinite, this procedure does not return.
553
554<enscript highlight=scheme>(stream-count even? (stream 3 1 4 1 5 9 2 5 6))
555=> 3
556(stream-count < (stream 1 2 4 8) (stream 2 4 6 8 10 12 14 16))
557=> 3
558(stream-count < (stream 3 1 4 1) (make-stream #t 2))
559=> 2</enscript>
560
561== Filtering & Partitioning
562
563=== stream-partition
564
565 [procedure] (stream-partition pred str)
566
567Partitions the elements of stream {{str}} with predicate
568{{pred}}, and returns two values: the stream of in-elements
569and the stream of out-elements.
570The stream is not disordered -- elements occur in the result streams
571in the same order as they occur in the argument stream.
572
573The dynamic order in which the various applications of {{pred}}
574depends on the evaluation of the streams.  {{pred}} might be evaluated
575twice for each element in the argument stream.
576
577<enscript highlight=scheme>(stream-partition symbol? (stream 'one 2 3 'four 'five 6))
578=>
579   #<stream (one four five)>
580   #<stream (2 3 6)></enscript>
581
582=== stream-remove
583
584 [procedure] (stream-remove pred str)
585
586Returns a stream with all the elements in the stream {{str}}
587except those that satisfy predicate pred:
588
589<enscript highlight=scheme>(lambda (pred str) (stream-filter (lambda (x) (not (pred x))) str))</enscript>
590
591The stream is not disordered -- elements that appear in the result list
592occur in the same order as they occur in the argument list.
593
594<enscript highlight=scheme>(stream-remove even? (stream 0 7 8 8 43 -4))
595=> #<stream (7 43)></enscript>
596
597== Searching
598
599=== stream-find
600
601 [procedure] (stream-find pred str)
602
603Return the first element of the stream {{str}}
604that satisfies predicate {{pred}};
605false if no element does.
606
607<enscript highlight=scheme>(stream-find even? (stream 3 1 4 1 5 9))
608=> 4</enscript>
609
610Note that {{stream-find}} has an ambiguity in
611its lookup semantics -- if find returns {{#f}},
612you cannot tell (in general) if it found a {{#f}} element that
613satisfied {{pred}}, or if it did not find any element at all.
614In many situations, this ambiguity cannot arise -- either the list
615being searched is known not to contain any {{#f}} elements, or the
616list is guaranteed to have an element satisfying {{pred}}.
617However, in cases where this ambiguity can arise, you should use
618{{stream-find-tail}} instead of {{stream-find}}
619-- {{stream-find-tail}} has no such ambiguity:
620
621<enscript highlight=scheme>(cond ((stream-find-tail pred lis) => (lambda (pair) ...)) ; Handle (CAR PAIR)
622      (else ...)) ; Search failed.</enscript>
623
624=== stream-find-tail
625
626 [procedure] (stream-find-tail pred str)
627
628Returns the first stream-pair of {{str}}
629whose car satisfies predicate {{pred}}.
630If no pair does, returns false.
631
632<enscript highlight=scheme>(stream-find-tail even? (stream 3 1 37 -8 -5 0 0))
633=> #<stream (-8 -5 0 0)>
634(stream-find-tail even? (stream 3 1 37 -5))
635=> #f</enscript>
636
637{{stream-find-tail}} can be viewed as a general-predicate
638variant of the {{stream-member}} function.  {{stream-member}}
639can be defined as a call to stream-find-tail:
640
641<enscript highlight=scheme>;; (stream-member x str):
642(stream-find-tail (lambda (elt) (equal? x elt)) str)</enscript>
643
644Find-tail is essentially stream-drop-while, where the sense of the
645predicate is inverted: Find-tail searches until it finds an element
646satisfying the predicate; drop-while searches until it finds an
647element that doesn't satisfy the predicate.
648
649=== stream-take-while
650
651 [procedure] (stream-take-while pred str)
652
653Returns the longest initial prefix of stream {{str}}
654whose elements all satisfy the predicate {{pred}}.
655
656<enscript highlight=scheme>(stream-take-while even? (stream 2 18 3 10 22 9))
657=> #<stream (2 18)></enscript>
658
659=== stream-drop-while
660
661 [procedure] (stream-drop-while pred str)
662
663Drops the longest initial prefix of stream {{str}} whose
664elements all satisfy the predicate {{pred}} and returns
665the rest of the stream.
666
667<enscript highlight=scheme>(stream-drop-while even? (stream 2 18 3 10 22 9))
668=> #<stream (3 10 22 9)></enscript>
669
670=== stream-span, stream-break
671
672 [procedure] (stream-span pred str)
673 [procedure] (stream-break pred str)
674
675{{stream-span}} splits the stream {{str}} into the longest
676initial prefix whose elements all satisfy predicate {{pred}}, and the
677remaining tail.  {{stream-break}} inverts the sense of the predicate:
678the tail commences with the first element of the input list that satisfies the
679predicate.
680
681In other words: {{stream-span}} finds the intial span of elements
682satisfying {{pred}}, and {{stream-break}} breaks the list at
683the first element not satisfying {{pred}}.
684
685stream-span is equivalent to:
686
687<enscript highlight=scheme>(values (stream-take-while pred str) (stream-drop-while pred str))</enscript>
688
689Examples:
690
691<enscript highlight=scheme>(stream-span even? (stream 2 18 3 10 22 9))
692=>
693  #<stream (2 18)>
694  #<stream (3 10 22 9)>
695(stream-break even? (stream 3 1 4 1 5 9))
696=>
697  #<stream (3 1)>
698  #<stream (4 1 5 9)></enscript>
699
700=== stream-any
701
702 [procedure] (stream-any pred str1 str2 ...)
703
704Applies the predicate {{pred}}
705across the streams {{str1 ... strn}},
706returning true if the predicate returns true on any application.
707
708If there are {{n}} stream arguments
709{{str1 ... strn}}, then {{pred}}
710must be a procedure taking {{n}} arguments
711and returning a boolean result.
712
713{{stream-any}} applies {{pred}} to the first
714elements of the {{stri}} parameters.
715If this application returns a true value, {{stream-any}}
716immediately returns that value. Otherwise, it iterates, applying
717{{pred}} to the second elements of the {{stri}}
718parameters, then the third, and so forth. The iteration stops when
719a true value is produced or one of the streams runs out of values;
720in the latter case, {{stream-any}} returns #f.
721
722Just like with {{any}} (see SRFI-1), it would be desirable
723to make the last call to {{pred}} a tail call.  However,
724this would force {{stream-any}} to evaluate streams in
725advance.  For this reason, the last call to {{pred}} is
726not a tail call.
727
728Note the difference between {{stream-find}}
729and {{stream-any}} -- {{stream-find}} returns the element that
730satisfied the predicate; {{stream-any}} returns the true value that the
731predicate produced.
732
733Like {{stream-every}}, {{stream-any}}'s name
734does not end with a question mark -- this is to indicate that it
735does not return a simple boolean ({{#t}} or {{#f}}),
736but a general value.
737
738<enscript highlight=scheme>(stream-any integer? (stream 'a 3 'b 2.7))
739=> #t
740(stream-any integer? (stream 'a 3.1 'b 2.7))
741=> #f
742(stream-any < (stream 3 1 4 1 5) (stream 2 7 1 8 2))
743=> #t</enscript>
744
745=== stream-every
746
747 [procedure] (stream-every pred str1 str2 ...)
748
749Applies the predicate across the streams,
750returning true if the predicate returns true on every application.
751
752If there are {{n}} stream arguments
753{{str1 ... strn}}, then {{pred}} must be a procedure
754taking {{n}} arguments and returning a boolean result.
755
756{{stream-every}} applies {{pred}} to the first
757elements of the {{stri}} parameters. If this application
758returns false, {{stream-every}} immediately returns false.
759Otherwise, it iterates, applying {{pred}} to the second
760elements of the {{stri}} parameters, then the third, and
761so forth. The iteration stops when a false value is produced or one
762of the lists runs out of values. In the latter case, every returns
763the true value produced by its final application of pred.
764
765Just like with {{every}} (see SRFI-1), it would be desirable
766to make the last call to {{pred}} a tail call.  However,
767this would force {{stream-every}} to evaluate streams in
768advance.  For this reason, the last call to {{pred}} is
769not a tail call.
770
771If one of the {{stri}}
772has no elements, every simply returns #t.
773
774Like {{stream-any}}, {{stream-every}}'s
775name does not end with a question mark -- this is to indicate
776that it does not return a simple boolean (#t or #f), but a general value.
777
778=== stream-index
779
780 [procedure] (stream-index pred str1 str2 ...)
781
782Return the index of the leftmost elements in the
783streams that satisfies predicate {{pred}}.
784
785If there are {{n}} list arguments {{str1 ... strn}},
786then {{pred}} must be a function taking {{n}} arguments
787and returning a boolean result.
788
789stream-index applies {{pred}} to the first elements of the
790{{stri}} parameters. If this application returns true,
791{{stream-index}} immediately returns zero. Otherwise, it
792iterates, applying {{pred}} to the second elements of the
793{{stri}} parameters, then the third, and so forth. When it
794finds a tuple of list elements that cause {{pred}} to
795return true, it stops and returns the zero-based index of that
796position in the lists.
797
798The iteration stops when one of the lists runs out of values;
799in this case, {{stream-index}} returns {{#f}}.
800
801<enscript highlight=scheme>(stream-index even? (stream 3 1 4 1 5 9))
802=> 2
803(stream-index < (stream 3 1 4 1 5 9 2 5 6) (stream 2 7 1 8 2))
804=> 1
805(stream-index = (stream 3 1 4 1 5 9 2 5 6) (stream 2 7 1 8 2))
806=> #f</enscript>
807
808=== stream-member, stream-memq, stream-memv
809
810 [procedure] (stream-member x str [=])
811 [procedure] (stream-memq x str)
812 [procedure] (stream-memv x str)
813
814These procedures return the first substream of the
815stream {{str}}
816returned by {{(drop str i)}} for {{i}} less
817than the length of {{str}} whose stream-car is
818{{x}}.  If x does not occur in {{str}},
819then either #f is returned (for finite streams) or this
820call does not return.  {{stream-memq}} uses {{eq?}}
821to compare x with the elements of {{str}},
822while {{stream-memv}} uses {{eqv?}},
823and stream-member uses {{equal?}}.
824
825<enscript highlight=scheme>(stream-memq 'a (stream 'a 'b 'c))
826=> (a b c)
827(stream-memq 'b (stream 'a 'b 'c))
828=> (b c)
829(stream-memq 'a (stream 'b 'c 'd))
830=> #f
831(stream-memq (list 'a) (stream 'b '(a) 'c))
832=> #f
833(stream-member (list 'a) (stream 'b '(a) 'c))
834=> ((a) c)
835(stream-memq 101 (stream 100 101 102))
836=> *unspecified*
837(stream-memv 101 (stream 100 101 102))
838=> (101 102)</enscript>
839
840stream-member allows the client to pass in an optional equality procedure {{=}}
841used to compare elements.
842
843The comparison procedure is used to compare the elements {{ei}}
844of {{str}} to the element {{x}} in this way:
845
846<enscript highlight=scheme>(= x ei) ; str is (E1 ...)</enscript>
847
848That is, the first argument is always {{x}},
849and the second argument is one of the list elements.
850Thus one can reliably find the first element of {{str}} that
851is greater than five with {{(stream-member 5 list <)}}.
852
853Note that fully general list searching may be performed with
854the stream-find-tail and stream-find procedures, e.g.
855
856<enscript highlight=scheme>; Find the first pair with an even stream-car:
857(stream-find-tail even? str)</enscript>
858
859== Strings as streams
860
861=== stream-downcase
862
863 [procedure] (stream-downcase str)
864
865Returns a stream identical to the stream of characters {{str}} but
866with all characters converted to lowercase.
867
868=== stream-upcase
869
870 [procedure] (stream-upcase str)
871
872Returns a stream identical to the stream of characters {{str}} but
873with all characters converted to uppercase.
874
875== Deletion
876
877=== stream-delete
878
879 [procedure] (stream-delete x str [=])
880
881{{stream-delete}} returns a stream identical to {{str}}
882but removing all occurences of the element {{x}}.  The comparison
883procedure {{=}}, which defaults to {{equal?}}, is used to
884find them.
885
886The stream is not disordered -- elements that appear in the result stream
887occur in the same order as they occur in the argument stream.
888
889Note that fully general element deletion can be performed with the stream-remove procedure, e.g.:
890
891<enscript highlight=scheme>;; Delete all the even elements from STR:
892(stream-remove even? str)</enscript>
893
894The comparison procedure is used in this way: {{(= x ei)}}. That
895is, {{x}} is always the first argument, and a element from the stream
896is always the second argument.  Thus, one can reliably remove all the numbers
897greater than five from a stream with {{(delete 5 stream <)}}.
898
899=== stream-delete-duplicates
900
901 [procedure] (stream-delete-duplicates str [=])
902
903{{stream-delete-duplicates}} removes duplicate elements from the
904{{str}} stream argument.  If there are multiple equal elements in the
905argument stream, the result stream only contains the first or leftmost of these
906elements in the result. The order of these surviving elements is the same as in
907the original stream -- {{stream-delete-duplicates}} does not disorder
908the stream.
909
910The {{=}} parameter is used to compare the elements of the list; it
911defaults to {{equal?}}. If {{x}} comes before {{y}}
912in list, then the comparison is performed {{(= x y)}}.  The comparison
913procedure will be used to compare each pair of elements in list no more than
914once; the order in which it is applied to the various pairs is not
915specified.
916
917Be aware that, in general, {{stream-delete-duplicates}} runs in time O(n2) for
918n-streams lists. Uniquifying long lists can be accomplished in O(n lg n) time
919by sorting the stream to bring equal elements together, then using a linear-time
920algorithm to remove equal elements. Alternatively, one can use algorithms based
921on element-marking, with linear-time results.
922
923Also note that a list might be kept in memory with the entire contents
924of the stream during the execution of calls to this function.
925
926<enscript highlight=scheme>(stream-delete-duplicates (stream 0 1 0 3 0 1 3 4))
927=> #<stream (0 1 3 4)></enscript>
928
929== Version History
930
931;1.4.1: Small bug fix in {{stream-fold-right}}.
932;1.4 : Add {{stream-downcase}}, {{stream-upcase}}, {{vector->stream}}, {{stream->vector}}, {{stream-sort}}, {{stream-unlines}}, {{stream<}}, {{stream>}}, {{make-infinite-stream}}, {{stream-fold}}, {{stream-fold-right}} and {{stream-fold-right-delay}}.  Made {{make-stream}} and {{stream-tabulate}} receive an optional {{tail}} argument.  Many bug fixes.
933;1.3.1: Replaced use of {{(end-of-file)}} with {{#!eof}}
934;1.3 (r2136) : Made {{stream-reverse}} accept an optional parameter: the end of the list.  Made all parameters to {{stream->port}} optional (the port now defaults to the current input port).  Fixed {{stream-every}}.  Added {{stream->symbol}}, {{symbol->stream}}, {{stream-drop-safe}} and {{stream-take-safe}}.
935;1.2 (r1122) : Added {{list->stream}}, {{number->stream}}, {{stream->number}}, {{stream-intersperse}}, {{stream-last-n}}, {{stream-butlast}}, {{stream-butlast-n}}, {{iterator->stream}}, {{call-with-output-stream}} and {{call-with-input-stream}}; and fixed {{stream-delete-duplicates}}, {{stream-find}} and {{stream-find-tail}}.
936;1.1 : Removed {{stream-filter}} (it's provided by srfi-40).
937;1.0 : First public release.
Note: See TracBrowser for help on using the repository browser.