> SRFI-40 is deprecated due to a memory leak. Please port SRFI-41 instead,
> and adapt any code that uses SRFI-40 to the new interface.
Did you, during the design of srfi-41, consider the existance of the
stream-ext library, which implements a lot of stream functions on top
of srfi-40?
http://chicken.wiki.br/eggref/3/stream-ext
It's first version was released a long time before srfi-41 and only
small changes have been made since then. The naming conventions and
the semantics match those of srfi-1 as close as possible, to make
things as consistent as possible.
I've used the stream-ext library in many applications that represent
strings as streams of characters throughout. The largest of these is
probably Svnwiki.
I'm worried about the incompatibilities I see between stream-ext and
srfi-41. My concerns are the following:
1. srfi-41 provides a very small subset of the functionality that I
think that any program that uses streams significantly will need. As
such, I think it fails significantly at providing "syntax derived from
those primitives that permits convenient expression of stream
operations". Most of the functions I list below can be implemented in
a portable manner, as stream-ext does. To be fair, srfi-41 does seem
to provide some functions that stream-ext does not.
2. More importantly (the previous concern can be solved with an
additional library), a small portion of the interface exported by
srfi-41 differs from that in the stream-ext library. I provide some
cases below and explain why I believe the semantics from stream-ext
are slightly preferable, mostly because of consistency with the srfi-1
list-based counterparts. I quite like the interface of srfi-1 and I
find that, by providing inconsistent counterparts, srfi-41 is making
it slightly harder to use streams than stream-ext.
I may be the person who has written the most Scheme code using srfi-40
streams. I've put special care into the design of the interface of
the stream-ext library. This interest I have in using streams in
Scheme makes the fact that srfi-41 offers an inferior interface rather
frustrating for me.
Now onto the differences and similarities:
The following is a list of symbols provided by stream-ext and srfi-41
with apparently the exact same semantics:
list->stream
stream-ref
stream-length
stream-append
stream-take-while
stream-drop-while
The following is a list of symbols available in stream-ext but not in
srfi-41, which I believe most software using streams would benefit
from:
stream-xcons
stream-cons*
stream-tabulate
stream-iota
make-infinite-stream
I think these should be included as counterparts to the srfi-1
versions for lists. The make-infinite-stream should probably be
added (see stream-ext's make-stream, discussed bellow).
stream->string
string->stream
stream-downcase, stream-upcase
stream-lines
stream-unlines
I think these should be included: if one does include
port->stream, encouraging the use of streams of characters to
represent ports/streams, why not go the extra mile of simplifying
conversion to and from strings and handling of streams of
characters?
stream->vector
vector->stream
number->stream
stream->number
stream->symbol
symbol->stream
And if we include the stream->string and string->stream symbols,
encouraging the programmer to use streams throughout his program
to represent strings, these should probably also be included,
specially the vector ones. I don't think we should force all
programs that use streams to define this compositions directly.
iterator->stream
This is a fundamental block for turning iterators into streams.
I've found it extremely useful in my programs that use streams.
For example, list->stream can be trivially implemented as:
(define (list->stream l)
(iterator->stream
(lambda (return stop)
(for-each return l))))
Among *many* other things, this makes it trivial to do things like
'with-output-to-stream', given the right support from the
implementation (for creating special ports). Also,
iterator->stream does not depend on anything non-portable, simply
on call/cc.
write-stream
The counter-part to port->stream. Most of my programs have a lot
of functions that generate streams (see for example my html-stream
library). A lot of these will be wrapped in a simple call to
write-stream, to output these to the right port. I think it
should be included in a general purpose streams library.
stream=
stream-prefix=
stream>, stream<
stream-caar ... stream-cddddr
stream-first ... stream-tenth
stream-intersperse
stream-split
stream-last
stream-last-n
stream-butlast
stream-butlast-n
stream-length>=
stream-count
stream-partition
stream-remove
stream-sort
stream-find
stream-find-tail
stream-any
stream-every
I'm using all these quite often. I feel all of them deserve
inclussion in a general purpose for construction of streams. I
think this is obvious enough that I won't waste my time justifying
it. If you think a given one of these should not be included, ask
me and I'll explain why I think it should.
I find it a bit surprising that stream-partition, stream-remove,
stream-find and stream-sort were not included in the library, even
though they were considered general enough that they were defined
as examples (though stream-sort is implemented using merge-sort).
with-output-to-stream
Very convenient for turning code that generates output to its
current-output-port into code that builds a (lazy, obviously)
stream. However, I suppose this can't be implemented in a
portable manner. :-/
with-input-from-stream
The rationale is very similar to that of with-output-to-stream.
However, I've found this procedure a bit less useful than the
other.
The following is a list of symbols provided by stream-ext with
semantics incompatible with those of srfi-41. I believe the
definition in stream-ext is more adequate for the reasons I explain.
make-stream
stream-ext's definition matches the counterpart from srfi-1's
make-list. srfi-41 defines this but, fortunately, does not export
it.
stream->list
I don't like the idea of the optional number-of-elements
arguments. This should simply work only on finite streams (and
one should use stream-take for infinite streams). I think
stream-ext's definition is more adequate as it more commonly
reflects the expectation from the programmer (of just converting a
stream to its corresponding list); taking the head of the list
should not be done by this function. I also tend to dislike
optional parameters preceeding mandatory parameters.
port->stream
The interface described in srfi-41 is a subset of that in
stream-ext: stream-ext adds two optional parameters that make this
procedure a lot more flexible/usable, without any disadvantages.
stream-take, stream-take-safe
stream-drop, stream-drop-safe
These are *almost* compatible. The only difference is that, in
consistence with srfi-1, I've decided to make it an error to take
more elements than the stream has. srfi-41, instead, has decided
to not make it an error. I prefer the stream-ext behavior simply
for being consistent with what the srfi-1 counterparts do. I want
to make the streams and lists libraries as compatible as possible.
stream-concatenate
srfi-41 decided to call this stream-concat, which is inconsistent
with srfi-1. I prefer stream-ext's consistent naming convention.
stream-reverse
This is *almost* compatible, but stream-ext allows the caller to
pass a list to be appended to the result, which I think makes the
procedure slightly more useful.
The following are other symbols in stream-ext that I haven't had time
to compare with those in srfi-41:
stream-fold
stream-fold-right
stream-fold-right-delay
stream-span, stream-break
stream-index
stream-member, stream-memq, stream-memv
stream-format
stream-delete
stream-delete-duplicates
I suspect the fold procedures provided by stream-ext are far more
usable than those in srfi-41, but, as I said, I haven't had time to
compare them.
The following are symbols in srfi-41 and not in srfi-40 that I haven't
had time to compare with those in stream-ext:
stream-lambda
define-stream
stream-constant
stream-fold
stream-from
stream-iterate
stream-let
stream-match
stream-of
stream-range
stream-scan
stream-unfold
stream-unfolds
stream-zip
Thanks.
Alejo.
http://azul.freaks-unidos.net/