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.