|
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