[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [ikarus-users] questions on the streams library



Thanks for the kind words about the text file database paper.  It's just a simple library, not really SRFI material, though it might fit in one or more of the Scheme code repositories.

I like comprehensions, too.  Here are my versions of list-of and fold-of:
(define-syntax list-of
(syntax-rules (range in is)
((_ "aux" expr base)
(cons expr base))
((_ "aux" expr base (x range first past step) clauses ...)
(let ((more? (if (positive? step) < >)))
(let loop ((z first))
(if (more? z past)
(let ((x z))
(list-of "aux" expr (loop (+ z step)) clauses ...))
base))))
((_ "aux" expr base (x range first past) clauses ...)
(let* ((step (if (< first past) 1 -1))
(more? (if (positive? step) < >)))
(let loop ((z first))
(if (more? z past)
(let ((x z))
(list-of "aux" expr (loop (+ z step)) clauses ...))
base))))
((_ "aux" expr base (x in xs) clauses ...)
(let loop ((z xs))
(if (null? z)
base
(let ((x (car z)))
(list-of "aux" expr (loop (cdr z)) clauses ...)))))
((_ "aux" expr base (x is y) clauses ...)
(let ((x y))
(list-of "aux" expr base clauses ...)))
((_ "aux" expr base pred? clauses ...)
(if pred?
(list-of "aux" expr base clauses ...)
base))
((_ expr clauses ...)

(define-syntax fold-of
(syntax-rules (range in is)
((_ "aux" op base expr)
(op expr base))
((_ "aux" op base expr (x range first past step) clauses ...)
(let ((more? (if (positive? step) < >)))
(let loop ((z first))
(if (more? z past)
(let ((x z))
(fold-of "aux" op (loop (+ z step)) expr clauses ...))
base))))
((_ "aux" op base expr (x range first past) clauses ...)
(let* ((step (if (< first past) 1 -1))
(more? (if (positive? step) < >)))
(let loop ((z first))
(if (more? z past)
(let ((x z))
(fold-of "aux" op (loop (+ z step)) expr clauses ...))
base))))
((_ "aux" op base expr (x in xs) clauses ...)
(let loop ((z xs))
(if (null? z)
base
(let ((x (car z)))
(fold-of "aux" op (loop (cdr z)) expr clauses ...)))))
((_ "aux" op base expr (x is y) clauses ...)
(let ((x y))
(fold-of "aux" op base expr clauses ...)))
((_ "aux" op base expr pred? clauses ...)
(if pred?
(fold-of "aux" op base expr clauses ...)
base))
((_ op base expr clauses ...)
(fold-of "aux" op base expr clauses ...))))
(list-of "aux" expr '() clauses ...))))
The stream SRFI is best discussed on the post-finalization discussion list of the SRFI itself.  But since you asked here, I'll answer here, and send a copy to the SRFI.

Thank you for "really really" liking it.  Have you used streams "in anger" in a real program?

There is nothing wrong with port->stream.  If you open a port, then pass it to port->stream, all will be fine; in fact, that's exactly what file->stream does.  The problem is with with-input-from-file, which is eager.  Since I anticipated that many users would expect to use port->stream to read a file, and the naive usage is incorrect, I included a proper implementation as a comment in the SRFI.  I did not include file->stream in the SRFI directly out of a sense of minimalism; likewise, there is no file->stream-lines.  There is no error-handling in port->stream or file->stream because there is no error-handling in R5RS, and there was no R6RS implementation available at the time I wrote the SRFI.

Stream-equal? is only defined on finite streams; it has no meaning on infinite streams.  And as the SRFI suggests, if you are materializing all the elements of a finite stream, you may as well be using a list.

A comment on minimalism:  I found the hardest part of writing the SRFI to be knowing where to stop.  Once you have port->stream, it makes sense to add file->stream.  Once you have file->stream, it makes sense to add text-file->stream-lines.  Once you have text-file->stream-lines, it makes sense to add csv-file->stream-fielded-lines.  Once you have ....  My motto during the writing of the SRFI was "When in doubt, leave it out."  I'm not sure I got everything exactly right, but I think the result is pretty close.  It pains me when someone writes (on the PLT mailing list) that the PLT version of the SRFI will "obviously" have to be extended to include stream-partition; it is certainly not obvious to me!  If I had the opportunity to do it again, I would probably exclude stream-constant; it was originally included to support an example program, but when the example got dropped from the SRFI (I found a better example to illustrate the same point), I forgot to drop stream-constant.

Phil

On Sun, Apr 6, 2008 at 10:56 AM, Michele Simionato <michele.simionato@xxxxxxxxx> wrote:

On Apr 4, 4:49 pm, "Phil Bewig" <pbe...@xxxxxxxxx> wrote:
> You might find some useful ideas for processing csv files here:
>
> schemephil.googlepages.com/TextFileDatabases.pdf
>
> Phil


That was very instructive thanks. Do you plan to submit the CSV
library as an SRFI?
BTW, I take the opportunity to ask you a few questions about the
streams
SRFI (not sure if this is the proper forum but, oh well!).
I really really like the streams library and especially the
stream-comprehension syntax (I have even adapted it for lists).
Still, I have some question.

First of all, I don't see the point of port->stream. As soon you
introduce it, you say that it does not work as expected and you give a
recipe for converting files in streams:

(define-stream (file->stream filename)
 (let ((p (open-input-file filename)))
   (stream-let loop ((c (read-char p)))
     (if (eof-object? c)
         (begin (close-input-port p)
                stream-null)
         (stream-cons c
           (loop (read-char p)))))))

Why not to put file->stream directly in the library? When should I use
port->stream? Also, suppose there is a read error at some point. Can I
assume that the port will be closed properly? It does not look so from
the code. Also, for text files a file->stream function returning lines
would be much more useful than a function returning characters.

Final question: why stream-equal? is given as a recipe but not
included in the library? It seems useful enough to be included.
Ok, that was a lot of questions, but bear with me ;)

 Michele Simionato