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.
Nicolas