On Fri, Nov 27, 2009 at 4:40 PM, Igor Stasenko <siguctua@gmail.com> wrote:
2009/11/28 Nicolas Cellier <nicolas.cellier.aka.nice@gmail.com>:
> 2009/11/27 Eliot Miranda <eliot.miranda@gmail.com>:
>> An approach I like is to add an endOfStreamValue inst var to Stream and
>> answer its value when at end.  This way nil does not have to be the
>> endOfStreamValue, for example -1 might be much more convenient for a binary
>> stream, and streams can answer nil without confusing their clients.  atEnd
>> can be implemented as
>>     atEnd
>>         ^self peek = self endOfStreamValue
>> You can arrange to make streams raise an end-of-stream exception instead of
>> the endOfStreamValue by using some convention on the contents of
>> endOfStreamValue, such as if it is == to the stream itself (although I note
>> that in the Teleplace image the exception EndOfStrean is defined bit not
>> used).
>>
>> Of course, stream primitives get in the way of adding inst vars to stream
>> classes ;)
>> IMO this is a much more useful scheme than making nil the only endOfStream
>> value.
>>
>
> Last time I proposed to have an inst var endOfStreamAction was here
> http://lists.gforge.inria.fr/pipermail/pharo-project/2009-June/009536.html
> .
> Abusing nil value -> nil, I could even let this inst var
> un-initialized and be backward compatible
> (initializing with a ValueHolder on nil would do as well)
>

Nicolas, have you considered introducing methods which allow
graciously handle the end-of-stream while reading?
Something like:

nextIfAtEnd: aBlock
and
next: number ifAtEnd: aBlock


then caller may choose to either write:

char := stream nextIfAtEnd: [nil]

or handle end of stream differently, like leaving the loop:

char := stream nextIfAtEnd: [^ results]

the benefit of such approach that code which reads the stream , don't
needs to additionally
test stream state (atEnd) in iteration between #next sends neither
requires some unique value (like nil) returned by #next
when reaching end of stream.

IMO the block creation is too expensive for streams.  The defaultHandler approach for and EndOfStream exception is also too expensive.  The endOfStreamValue inst var is a nice trade-off between flexibility, efficiency and simplicity.  You can always write
     [(value := stream next) ~~ stream endOfStreamValue] whileTrue:
        [...do stuff...

 

> Nicolas
>


--
Best regards,
Igor Stasenko AKA sig.