Stream-filter and space leaks
Phil Bewig
(20 Feb 2003 14:08 UTC)
|
Re: Stream-filter and space leaks
Richard Kelsey
(20 Feb 2003 18:41 UTC)
|
Re: Stream-filter and space leaks
Phil Bewig
(21 Feb 2003 09:57 UTC)
|
Re: Stream-filter and space leaks
Richard Kelsey
(21 Feb 2003 23:18 UTC)
|
Re: Stream-filter and space leaks
sperber@xxxxxx
(21 Feb 2003 10:04 UTC)
|
Re: Stream-filter and space leaks
Richard Kelsey
(21 Feb 2003 15:06 UTC)
|
Re: Stream-filter and space leaks Matthias Neubauer (25 Feb 2003 16:01 UTC)
|
Re: Stream-filter and space leaks
Richard Kelsey
(25 Feb 2003 18:25 UTC)
|
Re: Stream-filter and space leaks
Matthias Neubauer
(25 Feb 2003 21:32 UTC)
|
Re: Stream-filter and space leaks
Richard Kelsey
(25 Feb 2003 22:11 UTC)
|
Re: Stream-filter and space leaks
sperber@xxxxxx
(26 Feb 2003 08:18 UTC)
|
Re: Stream-filter and space leaks
Matthias Neubauer
(26 Feb 2003 13:31 UTC)
|
Re: Stream-filter and space leaks
sperber@xxxxxx
(11 Mar 2003 14:58 UTC)
|
Re: Stream-filter and space leaks
Matthias Neubauer
(19 Mar 2003 15:27 UTC)
|
Re: Stream-filter and space leaks
felix
(22 Mar 2003 09:49 UTC)
|
Re: Stream-filter and space leaks
felix
(22 Mar 2003 09:56 UTC)
|
Richard Kelsey <xxxxxx@s48.org> writes: > From: xxxxxx@informatik.uni-tuebingen.de (Michael Sperber [Mr. Preprocessor]) > Date: Fri, 21 Feb 2003 11:04:03 +0100 > > The code you posted seems to be essentially the definition of > DELAY/FORCE from Scheme 48. However, Phil's old code does leak in > Scheme 48 and doesn't leak with the proposed fix. > > Right. I was mistaken about the source of the leak. This time around > I have actually tested the code. I tested it, too. And I am totally confused now, because I still see the space leak even *with* the proposed fix?! I, for my part, downloaded the current reference implementation as found on http://srfi.schemers.org/srfi-40/srfi-40.txt. The only thing that I then changed was that I replaced the former version of STREAM-FILTER by the one Phil posted last Thursday. When I load this into my scsh (0.6.3) and evaluate (stream-car (stream-filter (lambda (x) (zero? x)) (stream-from 1))) the whole thing dies pretty soon ejecting a post-gc interrupt---i.e, scsh seems to run out of memory. Enlightened by Richard's last post I afterwards tried another setup: I used the above implementation (i.e. the one with the _new_ implementation of STREAM-FILTER) but also replaced DELAY and FORCE by Richard's non-reentrant versions. Unfortunately I *still* see the space leak! So I suspect that either I use a bogus version of scsh, or I use completely different srfi implementation than you guys, or I am unable to operate scsh, or I don't know what else ... :-) Anyhow, I totally sympathize with Richard's approach. There should be only one general stream transformer (like stream-unfoldn) that is implemented in a space-safe way (if this is possible). Any other stream procedure should then be implemented with that, and as a consequence should also "work". For example, I'd like to be able to define something like (define (my-stream-filter pred? stream) (stream-unfoldn (lambda (stream) (let ((results (if (stream-null? stream) (list '() '()) (let* ((head (stream-car stream)) (test (pred? head))) (if test (list (list head) #f) (list #f (list head))))))) (values (stream-cdr stream) results))) stream 2)) and this should work! If this is not possible, I think the whole effort to make this srfi "space safe" should be abandoned completely. The only thing I am not sure about is, if STREAM-UNFOLDN is the right abstraction to transform streams (it looks a little bit too "heavy weight" to me ...). Last summer I learned about another way to transform streams: Richard Bird and Jeremy Gibbons proposed in [1, page 26] a stream transformer "stream" that transforms one stream into another by alternating between consuming and producing stream elements. To my mind, this seems a little bit "simpler". In addition, this function also has some nice properties; it allows you to "fuse" unfolds with folds, which I think could be very neat, too. I just tried to code it (I named it STREAM-TRANSFORM for now): (define (stream-transform producer consumer state stream) (define (loop state stream) (if (null? (stream-value stream)) (stream-value (stream-prepend (car (producer state)) stream-null)) (if (null? (car (producer state))) (loop (consumer (cdr (producer state)) (car (stream-value stream))) (cdr (stream-value stream))) (let ((res (producer state))) (stream-value (stream-prepend (car res) (make-stream (my-delay (loop (consumer (cdr res) (car (stream-value stream))) (cdr (stream-value stream))))))))))) (make-stream (my-delay (loop state stream)))) (stream-define (stream-prepend l stream) (let inner-loop ((l l)) (if (null? l) stream (stream-cons (car l) (inner-loop (cdr l)))))) (define (stream-value s) (my-force (stream-promise s))) With that, STREAM-FILTER is also very easy to define: (define (my-stream-filter-2 pred? stream) (stream-transform (lambda (state) (cons (if state (list state) '()) 'foo)) (lambda (foo c) (if (pred? c) c #f)) #f stream)) Works, but is also not space-safe yet ... Cheers, Matthias [1] http://www.cs.uu.nl/~johanj/afp/afp4/arith-4.pdf -- Matthias Neubauer | Universität Freiburg, Institut für Informatik | tel +49 761 203 8060 Georges-Köhler-Allee 79, 79110 Freiburg i. Br., Germany | fax +49 761 203 8052