Hi Alistair.

I don't think anybody is annoyed by you. You are doing really good job. And
nice thing that you are super patient to continue :)

What I try to understand is why blocking atEnd is bad?
Here is code from VMMaker:

[stdin atEnd] whileFalse:
[| nextChunk |
stdout nextPutAll: 'squeak> '; flush.
nextChunk := stdin nextChunkNoTag.
[nextChunk notEmpty and: [nextChunk first isSeparator]] whileTrue:
[nextChunk := nextChunk allButFirst].
Transcript cr; nextPutAll: nextChunk; cr; flush.
[stdout print: (Compiler evaluate: nextChunk); cr; flush]
on: Error
do: [:ex| self logError: ex description inContext: ex signalerContext to:
stderr]].
quitOnEof ifTrue:
[SourceFiles at: 2 put: nil.
Smalltalk snapshot: false andQuit: true]


I am not see why it breaks with blocking #atEnd. Can you explain?

2018-04-11 11:41 GMT+02:00 Alistair Grant <akgrant0...@gmail.com>:

> Hi Sven,
>
> Oh dear.  I feel as though I'm not getting my concerns across at all
> well, and I'm pushing hard enough that all I'm going to do is make
> people annoyed.  So let me try to restate the issue one last time
> before answering your questions directly.
>
> Pharo & Squeak have unwritten rules about stream usage that I suspect
> have just emerged over time without being designed.
>
> If you want to be able to iterate over any stream, and in particular
> stdin from a terminal (which, as far as I know, is the outlier that
> causes all the problems) you have to follow these rules:
>
> 1.  If the stream is character / byte oriented you have to check for
> EOF using "stream next == nil".  #atEnd can be used, but you'll still
> have to do the nil check.
>
> 2.  All other streams have to check for EOF (end of stream) using
> #atEnd.  "stream next == nil" can be used, but you'll still need to
> test #atEnd to determine whether nil is a value returned by the
> stream.
>
> If you write code that you want to be able to consume characters,
> bytes or any other object, you'll have to test both "stream next ==
> nil" and #atEnd.
>
> The rules are the result of the original blue book design being that
> #atEnd should be used, and then character input from a terminal being
> added later, but always returning an EOF character (nil) before #atEnd
> answers correctly.
>
> At the moment, ZnCharacterEncoder uses #atEnd on character / byte
> streams, so fails for stdin on a terminal.
>
> Back to your questions:
>
> On 11 April 2018 at 11:12, Sven Van Caekenberghe <s...@stfx.eu> wrote:
> >
> >
> >> On 11 Apr 2018, at 10:29, Alistair Grant <akgrant0...@gmail.com> wrote:
> >>
> >> Hi Denis,
> >>
> >> On 11 April 2018 at 10:02, Denis Kudriashov <dionisi...@gmail.com>
> wrote:
> >>>
> >>> 2018-04-11 8:32 GMT+02:00 Alistair Grant <akgrant0...@gmail.com>:
> >>>>
> >>>>>>> Where is it being said that #next and/or #atEnd should be blocking
> or
> >>>>>>> non-blocking ?
> >>>>>>
> >>>>>> There is existing code that assumes that #atEnd is non-blocking and
> >>>>>> that #next is allowed block.  I believe that we should keep those
> >>>>>> conditions.
> >>>>>
> >>>>> I fail to see where that is written down, either way. Can you point
> me
> >>>>> to comments stating that, I would really like to know ?
> >>>>
> >>>> I'm not aware of it being written down, just that ever existing
> >>>> implementation I'm aware of behaves this way.
> >>>>
> >>>> On the other hand, making #atEnd blocking breaks Eliot's REPL sample
> >>>> (in Squeak).
> >>>
> >>>
> >>> Could you write here this example, please?
> >>
> >> The code is loaded in squeak using:
> >>
> >> https://github.com/OpenSmalltalk/opensmalltalk-vm/blob/Cog/image/
> buildspurtrunkreaderimage.sh
> >>
> >> for 32 bit images.  It loads:
> >>
> >> https://github.com/OpenSmalltalk/opensmalltalk-
> vm/blob/Cog/image/LoadReader.st
> >>
> >> which loads package CogTools-Listener in http://source.squeak.org/
> VMMaker
> >>
> >> An image that automatically runs the code and nothing else is created
> in:
> >>
> >> https://github.com/OpenSmalltalk/opensmalltalk-
> vm/blob/Cog/image/StartReader.st
> >>
> >>
> >> If you want to run it interactively you can load CogTools-Listener and
> >> do something like:
> >>
> >> StdioListener new
> >>    quitOnEof: false;
> >>    run
> >
> > What does #quitOnEof: do ? Can the StdioListener code be browsed/viewed
> online somewhere ?
>
> I just referenced this as an example of making #atEnd (really
> FilePlugin>>primitiveFileAtEnd) blocking causing problems.  I wasn't
> expecting people to go and look at the code or use it as a test.
>
> If you really want to look at it (from Pharo):
>
> 1. Add http://source.squeak.org/VMMaker as a repository.
> 2. Browse the CogTools-Listener package
>
>
> >> If you modify #atEnd to block it will result in the "squeak>" input
> >> prompt being printed in the terminal after the input has been entered.
> >
> > How does one modify #atEnd to block ? I suppose you are talking about
> StdioStream>>#atEnd ?
>
> I meant the primitive, i.e. FilePlugin>>primitiveFileAtEnd /
> FilePluginPrims>>atEnd:.
>
>
> >  ^ self peek isNil
> >
> > ?
> >
> > PS: I liked your runnable example better, I will try it later on. Thx!
>
> Right.  My code is meant to be minimal and trigger the problem I'm
> actually focused on - that ZnCharacterEncoder doesn't work with stdin
> from a terminal.
>
> Sven has expressed a hesitation to change the internal operation of
> the Zinc streams from using #atEnd to "stream peek == nil" and this
> whole discussion is really about us trying to resolve our different
> perspective of the best path forward.  I respect Sven and his work so
> I'm trying to justify the change (but I'm not expressing it at all
> well, obviously).
>
> Cheers,
> Alistair
>
>
>
> >> The code can be loaded in to Pharo and basically works, but the output
> >> tends to be hidden behind the next input prompt because it uses #cr
> >> instead of #lf.  You can easily modify StdioListener>>initialize to
> >> set the line end convention in stdout.
> >>
> >> NOTE: It is not intended to be a release quality implementation of a
> >> evaluation loop.  The whole purpose as I understand it is for it to be
> >> as simple as possible to assist in tracking down issues using the VM
> >> simulator.  It runs minimal code to get to the point of waiting for
> >> user input and then allows an expression that causes problems to be
> >> entered and traced using the simulator.
> >>
> >> Cheers,
> >> Alistair
> >>
> >>
> >>
> >>>>>>> How is this related to how EOF is signalled ?
> >>>>>>
> >>>>>> Because, combined with terminal EOF not being known until the user
> >>>>>> explicitly flags it (with Ctrl-D) it means that #atEnd can't be used
> >>>>>> for iterating over input from stdin connected to a terminal.
> >>>>>
> >>>>> This seems to me like an exception that only holds for one particular
> >>>>> stream in one particular scenario (interactive stdin). I might be
> wrong.
> >>>>>
> >>>>>>> It seems to me that there are quite a few classes of streams that
> are
> >>>>>>> 'special' in the sense that #next could be blocking and/or #atEnd
> could be
> >>>>>>> unclear - socket/network streams, serial streams, maybe stdio
> (interactive
> >>>>>>> or not). Without a message like #isDataAvailable you cannot handle
> those
> >>>>>>> without blocking.
> >>>>>>
> >>>>>> Right.  I think this is a distraction (I was trying to explain some
> >>>>>> details, but it's causing more confusion instead of helping).
> >>>>>>
> >>>>>> The important point is that #atEnd doesn't work for iterating over
> >>>>>> streams with terminal input
> >>>>>
> >>>>> Maybe you should also point to the actual code that fails. I mean you
> >>>>> showed a partial stack trace, but not how you got there, precisely.
> How does
> >>>>> the application reading from an interactive stdin do to get into
> trouble ?
> >>>>
> >>>> Included below.
> >>>>
> >>>>
> >>>>>>> Reading from stdin seems like a very rare case for a Smalltalk
> system
> >>>>>>> (not that it should not be possible).
> >>>>>>
> >>>>>> There's been quite a bit of discussion and several projects recently
> >>>>>> related to using pharo for scripting, so it may become more common.
> >>>>>> E.g.
> >>>>>>
> >>>>>>
> >>>>>> https://www.quora.com/Can-Smalltalk-be-a-batch-file-
> scripting-language/answer/Philippe-Back-1?share=c19bfc95
> >>>>>> https://github.com/rajula96reddy/pharo-cli
> >>>>>
> >>>>> Still, it is not common at all.
> >>>>>
> >>>>>>> I have a feeling that too much functionality is being pushed into
> too
> >>>>>>> small an API.
> >>>>>>
> >>>>>> This is just about how should Zinc streams be iterating over the
> >>>>>> underlying streams.  You didn't like checking the result of #next
> for
> >>>>>> nil since it isn't general, correctly pointing out that nil is a
> valid
> >>>>>> value for non-byte oriented streams.  But #atEnd doesn't work for
> >>>>>> stdin from a terminal.
> >>>>>>
> >>>>>>
> >>>>>> At this point I think there are three options:
> >>>>>>
> >>>>>> 1. Modify Zinc to check the return value of #next instead of using
> >>>>>> #atEnd.
> >>>>>>
> >>>>>> This is what all existing character / byte oriented streams in
> Squeak
> >>>>>> and Pharo do.  At that point the Zinc streams can be used on all
> file
> >>>>>> / stdio input and output.
> >>>>>
> >>>>> I agree that such code exists in many places, but there is lots of
> >>>>> stream reading that does not check for nils.
> >>>>
> >>>> Right.  Streams can be categorised in many ways, but for this
> >>>> discussion I think streams are broken in to two types:
> >>>>
> >>>> 1) Byte / Character oriented
> >>>> 2) All others
> >>>>
> >>>> For historical reasons, byte / character oriented streams need to
> >>>> check for EOF by using "stream next == nil" and all other streams
> >>>> should use #atEnd.
> >>>>
> >>>> This avoids the "nil being part of the domain" issue that was
> >>>> discussed earlier in the thread.
> >>>>
> >>>>
> >>>>>> 2. Modify all streams to signal EOF in some other way, i.e. a
> sentinel
> >>>>>> or notification / exception.
> >>>>>>
> >>>>>> This is what we were discussing below.  But it is a decent chunk of
> >>>>>> work with significant impact on the existing code base.
> >>>>>
> >>>>> Agreed. This would be a future extension.
> >>>>>
> >>>>>> 3. Require anyone who wants to read from stdin to code around Zinc's
> >>>>>> inability to handle terminal input.
> >>>>>>
> >>>>>> I'd prefer to avoid this option if possible.
> >>>>>
> >>>>> See higher for a more concrete usage example request.
> >>>>
> >>>>
> >>>> testAtEnd.st
> >>>> --
> >>>> | ch stream string stdin |
> >>>>
> >>>> 'stdio.cs' asFileReference fileIn.
> >>>> "stdin := FileStream stdin."
> >>>> stdin := ZnCharacterReadStream on:
> >>>>    (ZnBufferedReadStream on:
> >>>>        Stdio stdin).
> >>>> stream := (String new: 100) writeStream.
> >>>> ch := stdin next.
> >>>> [ ch == nil ] whileFalse: [
> >>>>    stream nextPut: ch.
> >>>>    ch := stdin next. ].
> >>>> string := stream contents.
> >>>> FileStream stdout
> >>>>    nextPutAll: string; lf;
> >>>>    nextPutAll: 'Characters read: ';
> >>>>    nextPutAll: string size asString;
> >>>>    lf.
> >>>> Smalltalk snapshot: false andQuit: true.
> >>>> --
> >>>>
> >>>> Execute with:
> >>>>
> >>>> ./pharo --headless Pharo7.0-64bit-e76f1a2.image testAtEnd.st
> >>>>
> >>>> and type Ctrl-D gives:
> >>>>
> >>>>
> >>>> 'Errors in script loaded from testAtEnd.st'
> >>>> MessageNotUnderstood: receiver of "<" is nil
> >>>> UndefinedObject(Object)>>doesNotUnderstand: #<
> >>>> ZnUTF8Encoder>>nextCodePointFromStream:
> >>>> ZnUTF8Encoder(ZnCharacterEncoder)>>nextFromStream:
> >>>> ZnCharacterReadStream>>nextElement
> >>>> ZnCharacterReadStream(ZnEncodedReadStream)>>next
> >>>> UndefinedObject>>DoIt
> >>>> OpalCompiler>>evaluate
> >>>>
> >>>>
> >>>> Using #atEnd to control the loop instead of "stdin next == nil"
> >>>> produces the same result.
> >>>>
> >>>> Replacing stdin with FileStream stdin makes the script work.
> >>>>
> >>>> stdio.cs fixes a bug in StdioStream which really isn't part of this
> >>>> discussion (PR to be submitted).
> >>>>
> >>>> Cheers,
> >>>> Alistair
> >>>>
> >>>>
> >>>>
> >>>>
> >>>>>> Does that clarify the situation?
> >>>>>
> >>>>> Yes, it helps. Thanks. But questions remain.
> >>>>>
> >>>>>> Thanks,
> >>>>>> Alistair
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>>> On 10 Apr 2018, at 18:30, Alistair Grant <akgrant0...@gmail.com>
> >>>>>>>> wrote:
> >>>>>>>>
> >>>>>>>> First a quick update:
> >>>>>>>>
> >>>>>>>> After doing some work on primitiveFileAtEnd, #atEnd now answers
> >>>>>>>> correctly for files that don't report their size correctly, e.g.
> >>>>>>>> /dev/urandom and /proc/cpuinfo, whether the files are opened
> directly
> >>>>>>>> or
> >>>>>>>> redirected through stdin.
> >>>>>>>>
> >>>>>>>> However determining whether stdin from a terminal has reached the
> end
> >>>>>>>> of
> >>>>>>>> file can't be done without making #atEnd blocking since we have to
> >>>>>>>> wait
> >>>>>>>> for the user to flag the end of file, e.g. by typing Ctrl-D.  And
> >>>>>>>> #atEnd
> >>>>>>>> is assumed to be non-blocking.
> >>>>>>>>
> >>>>>>>> So currently using ZnCharacterReadStream with stdin from a
> terminal
> >>>>>>>> will
> >>>>>>>> result in a stack dump similar to:
> >>>>>>>>
> >>>>>>>> MessageNotUnderstood: receiver of "<" is nil
> >>>>>>>> UndefinedObject(Object)>>doesNotUnderstand: #<
> >>>>>>>> ZnUTF8Encoder>>nextCodePointFromStream:
> >>>>>>>> ZnUTF8Encoder(ZnCharacterEncoder)>>nextFromStream:
> >>>>>>>> ZnCharacterReadStream>>nextElement
> >>>>>>>> ZnCharacterReadStream(ZnEncodedReadStream)>>next
> >>>>>>>> UndefinedObject>>DoIt
> >>>>>>>>
> >>>>>>>>
> >>>>>>>> Going back through the various suggestions that have been made
> >>>>>>>> regarding
> >>>>>>>> using a sentinel object vs. raising a notification / exception, my
> >>>>>>>> (still to be polished) suggestion is to:
> >>>>>>>>
> >>>>>>>> 1. Add an endOfStream instance variable
> >>>>>>>> 2. When the end of the stream is reached answer the value of the
> >>>>>>>> instance variable (i.e. the result of sending #value to the
> >>>>>>>> variable).
> >>>>>>>> 3. The initial default value would be a block that raises a
> >>>>>>>> Deprecation
> >>>>>>>> warning and then returns nil.  This would allow existing code to
> >>>>>>>> function for a changeover period.
> >>>>>>>> 4. At the end of the deprecation period the default value would be
> >>>>>>>> changed to a unique sentinel object which would answer itself as
> its
> >>>>>>>> #value.
> >>>>>>>>
> >>>>>>>> At any time users of the stream can set their own sentinel,
> including
> >>>>>>>> a
> >>>>>>>> block that raises an exception.
> >>>>>>>>
> >>>>>>>>
> >>>>>>>> Cheers,
> >>>>>>>> Alistair
> >>>>>>>>
> >>>>>>>>
> >>>>>>>> On 4 April 2018 at 19:24, Stephane Ducasse <
> stepharo.s...@gmail.com>
> >>>>>>>> wrote:
> >>>>>>>>> Thanks for this discussion.
> >>>>>>>>>
> >>>>>>>>> On Wed, Apr 4, 2018 at 1:37 PM, Sven Van Caekenberghe <
> s...@stfx.eu>
> >>>>>>>>> wrote:
> >>>>>>>>>> Alistair,
> >>>>>>>>>>
> >>>>>>>>>> First off, thanks for the discussions and your contributions, I
> >>>>>>>>>> really appreciate them.
> >>>>>>>>>>
> >>>>>>>>>> But I want to have a discussion at the high level of the
> definition
> >>>>>>>>>> and semantics of the stream API in Pharo.
> >>>>>>>>>>
> >>>>>>>>>>> On 4 Apr 2018, at 13:20, Alistair Grant <akgrant0...@gmail.com
> >
> >>>>>>>>>>> wrote:
> >>>>>>>>>>>
> >>>>>>>>>>> On 4 April 2018 at 12:56, Sven Van Caekenberghe <s...@stfx.eu>
> >>>>>>>>>>> wrote:
> >>>>>>>>>>>> Playing a bit devil's advocate, the idea is that, in general,
> >>>>>>>>>>>>
> >>>>>>>>>>>> [ stream atEnd] whileFalse: [ stream next. "..." ].
> >>>>>>>>>>>>
> >>>>>>>>>>>> is no longer allowed ?
> >>>>>>>>>>>
> >>>>>>>>>>> It hasn't been allowed "forever" [1].  It's just been misused
> for
> >>>>>>>>>>> almost as long.
> >>>>>>>>>>>
> >>>>>>>>>>> [1] Time began when stdio stream support was introduced. :-)
> >>>>>>>>>>
> >>>>>>>>>> I am still not convinced. Another way to put it would be that
> the
> >>>>>>>>>> old #atEnd or #upToEnd do not make sense for these streams and
> some new loop
> >>>>>>>>>> is needed, based on a new test (it exists for socket streams
> already).
> >>>>>>>>>>
> >>>>>>>>>> [ stream isDataAvailable ] whileTrue: [ stream next ]
> >>>>>>>>>>
> >>>>>>>>>>>> And you want to replace it with
> >>>>>>>>>>>>
> >>>>>>>>>>>> [ stream next ifNil: [ false ] ifNotNil: [ :x | "..." true ]
> >>>>>>>>>>>> whileTrue.
> >>>>>>>>>>>>
> >>>>>>>>>>>> That is a pretty big change, no ?
> >>>>>>>>>>>
> >>>>>>>>>>> That's the way quite a bit of code already operates.
> >>>>>>>>>>>
> >>>>>>>>>>> As Denis pointed out, it's obviously problematic in the general
> >>>>>>>>>>> sense,
> >>>>>>>>>>> since nil can be embedded in non-byte oriented streams.  I
> suspect
> >>>>>>>>>>> that in practice not many people write code that reads streams
> >>>>>>>>>>> from
> >>>>>>>>>>> both byte oriented and non-byte oriented streams.
> >>>>>>>>>>
> >>>>>>>>>> Maybe yes, maybe no. As Denis' example shows there is a clear
> >>>>>>>>>> definition problem.
> >>>>>>>>>>
> >>>>>>>>>> And I do use streams of byte arrays or strings all the time,
> this
> >>>>>>>>>> is really important. I want my parsers to work on all kinds of
> streams.
> >>>>>>>>>>
> >>>>>>>>>>>> I think/feel like a proper EOF exception would be better, more
> >>>>>>>>>>>> correct.
> >>>>>>>>>>>>
> >>>>>>>>>>>> [ [ stream next. "..." true ] on: EOF do: [ false ] ]
> whileTrue.
> >>>>>>>>>>>
> >>>>>>>>>>> I agree, but the email thread Nicolas pointed to raises some
> >>>>>>>>>>> performance questions about this approach.  It should be
> >>>>>>>>>>> straightforward to do a basic performance comparison which I'll
> >>>>>>>>>>> get
> >>>>>>>>>>> around to if other objections aren't raised.
> >>>>>>>>>>
> >>>>>>>>>> Reading in bigger blocks, using #readInto:startingAt:count:
> (which
> >>>>>>>>>> is basically Unix's (2) Read sys call), would solve performance
> problems, I
> >>>>>>>>>> think.
> >>>>>>>>>>
> >>>>>>>>>>>> Will we throw away #atEnd then ? Do we need it if we cannot
> use
> >>>>>>>>>>>> it ?
> >>>>>>>>>>>
> >>>>>>>>>>> Unix file i/o returns EOF if the end of file has been reach OR
> if
> >>>>>>>>>>> an
> >>>>>>>>>>> error occurs.  You should still check #atEnd after reading past
> >>>>>>>>>>> the
> >>>>>>>>>>> end of the file to make sure no error occurred.  Another part
> of
> >>>>>>>>>>> the
> >>>>>>>>>>> primitive change I'm proposing is to return additional
> information
> >>>>>>>>>>> about what went wrong in the event of an error.
> >>>>>>>>>>
> >>>>>>>>>> I am sorry, but this kind of semantics (the OR) is way too
> complex
> >>>>>>>>>> at the general image level, it is too specific and based on
> certain
> >>>>>>>>>> underlying implementation details.
> >>>>>>>>>>
> >>>>>>>>>> Sven
> >>>>>>>>>>
> >>>>>>>>>>> We could modify the read primitive so that it fails if an error
> >>>>>>>>>>> has
> >>>>>>>>>>> occurred, and then #atEnd wouldn't be required.
> >>>>>>>>>>>
> >>>>>>>>>>> Cheers,
> >>>>>>>>>>> Alistair
> >>>>>>>>>>>
> >>>>>>>>>>>
> >>>>>>>>>>>
> >>>>>>>>>>>>> On 4 Apr 2018, at 12:41, Alistair Grant <
> akgrant0...@gmail.com>
> >>>>>>>>>>>>> wrote:
> >>>>>>>>>>>>>
> >>>>>>>>>>>>> Hi Nicolas,
> >>>>>>>>>>>>>
> >>>>>>>>>>>>> On 4 April 2018 at 12:36, Nicolas Cellier
> >>>>>>>>>>>>> <nicolas.cellier.aka.n...@gmail.com> wrote:
> >>>>>>>>>>>>>>
> >>>>>>>>>>>>>>
> >>>>>>>>>>>>>> 2018-04-04 12:18 GMT+02:00 Alistair Grant
> >>>>>>>>>>>>>> <akgrant0...@gmail.com>:
> >>>>>>>>>>>>>>>
> >>>>>>>>>>>>>>> Hi Sven,
> >>>>>>>>>>>>>>>
> >>>>>>>>>>>>>>> On Wed, Apr 04, 2018 at 11:32:02AM +0200, Sven Van
> >>>>>>>>>>>>>>> Caekenberghe wrote:
> >>>>>>>>>>>>>>>> Somehow, somewhere there was a change to the
> implementation
> >>>>>>>>>>>>>>>> of the
> >>>>>>>>>>>>>>>> primitive called by some streams' #atEnd.
> >>>>>>>>>>>>>>>
> >>>>>>>>>>>>>>> That's a proposed change by me, but it hasn't been
> integrated
> >>>>>>>>>>>>>>> yet.  So
> >>>>>>>>>>>>>>> the discussion below should apply to the current stable vm
> >>>>>>>>>>>>>>> (from August
> >>>>>>>>>>>>>>> last year).
> >>>>>>>>>>>>>>>
> >>>>>>>>>>>>>>>
> >>>>>>>>>>>>>>>> IIRC, someone said it is implemented as 'remaining size
> being
> >>>>>>>>>>>>>>>> zero'
> >>>>>>>>>>>>>>>> and some virtual unix files like /dev/random are zero
> sized.
> >>>>>>>>>>>>>>>
> >>>>>>>>>>>>>>> Currently, for files other than sdio (stdout, stderr,
> stdin)
> >>>>>>>>>>>>>>> it is
> >>>>>>>>>>>>>>> effectively defined as:
> >>>>>>>>>>>>>>>
> >>>>>>>>>>>>>>> atEnd := stream position >= stream size
> >>>>>>>>>>>>>>>
> >>>>>>>>>>>>>>>
> >>>>>>>>>>>>>>> And, as you say, plenty of virtual unix files report size
> 0.
> >>>>>>>>>>>>>>>
> >>>>>>>>>>>>>>>
> >>>>>>>>>>>>>>>
> >>>>>>>>>>>>>>>> Now, all kinds of changes are being done image size to
> work
> >>>>>>>>>>>>>>>> around this.
> >>>>>>>>>>>>>>>
> >>>>>>>>>>>>>>> I would phrase this slightly differently :-)
> >>>>>>>>>>>>>>>
> >>>>>>>>>>>>>>> Some code does the right thing, while other code doesn't.
> >>>>>>>>>>>>>>> E.g.:
> >>>>>>>>>>>>>>>
> >>>>>>>>>>>>>>> MultiByteFileStream>>upToEnd is good, while
> >>>>>>>>>>>>>>> FileStream>>contents is incorrect
> >>>>>>>>>>>>>>>
> >>>>>>>>>>>>>>>
> >>>>>>>>>>>>>>>> I am a strong believer in simple, real (i.e. infinite)
> >>>>>>>>>>>>>>>> streams, but I
> >>>>>>>>>>>>>>>> am not sure we are doing the right thing here.
> >>>>>>>>>>>>>>>>
> >>>>>>>>>>>>>>>> Point is, I am not sure #next returning nil is official
> and
> >>>>>>>>>>>>>>>> universal.
> >>>>>>>>>>>>>>>>
> >>>>>>>>>>>>>>>> Consider the comments:
> >>>>>>>>>>>>>>>>
> >>>>>>>>>>>>>>>> Stream>>#next
> >>>>>>>>>>>>>>>> "Answer the next object accessible by the receiver."
> >>>>>>>>>>>>>>>>
> >>>>>>>>>>>>>>>> ReadStream>>#next
> >>>>>>>>>>>>>>>> "Primitive. Answer the next object in the Stream
> represented
> >>>>>>>>>>>>>>>> by the
> >>>>>>>>>>>>>>>> receiver. Fail if the collection of this stream is not an
> >>>>>>>>>>>>>>>> Array or a
> >>>>>>>>>>>>>>>> String.
> >>>>>>>>>>>>>>>> Fail if the stream is positioned at its end, or if the
> >>>>>>>>>>>>>>>> position is out
> >>>>>>>>>>>>>>>> of
> >>>>>>>>>>>>>>>> bounds in the collection. Optional. See Object
> documentation
> >>>>>>>>>>>>>>>> whatIsAPrimitive."
> >>>>>>>>>>>>>>>>
> >>>>>>>>>>>>>>>> Note how there is no talk about returning nil !
> >>>>>>>>>>>>>>>>
> >>>>>>>>>>>>>>>> I think we should discuss about this first.
> >>>>>>>>>>>>>>>>
> >>>>>>>>>>>>>>>> Was the low level change really correct and the right
> thing
> >>>>>>>>>>>>>>>> to do ?
> >>>>>>>>>>>>>>>
> >>>>>>>>>>>>>>> The primitive change proposed doesn't affect this
> discussion.
> >>>>>>>>>>>>>>> It will
> >>>>>>>>>>>>>>> mean that #atEnd returns false (correctly) sometimes, while
> >>>>>>>>>>>>>>> currently it
> >>>>>>>>>>>>>>> returns true (incorrectly).  The end result is still
> >>>>>>>>>>>>>>> incorrect, e.g.
> >>>>>>>>>>>>>>> #contents returns an empty string for /proc/cpuinfo.
> >>>>>>>>>>>>>>>
> >>>>>>>>>>>>>>> You're correct about no mention of nil, but we have:
> >>>>>>>>>>>>>>>
> >>>>>>>>>>>>>>> FileStream>>next
> >>>>>>>>>>>>>>>
> >>>>>>>>>>>>>>>    (position >= readLimit and: [self atEnd])
> >>>>>>>>>>>>>>>            ifTrue: [^nil]
> >>>>>>>>>>>>>>>            ifFalse: [^collection at: (position := position
> +
> >>>>>>>>>>>>>>> 1)]
> >>>>>>>>>>>>>>>
> >>>>>>>>>>>>>>>
> >>>>>>>>>>>>>>> which has been around for a long time (I suspect, before
> Pharo
> >>>>>>>>>>>>>>> existed).
> >>>>>>>>>>>>>>>
> >>>>>>>>>>>>>>> Having said that, I think that raising an exception is a
> >>>>>>>>>>>>>>> better
> >>>>>>>>>>>>>>> solution, but it is a much, much bigger change than the
> one I
> >>>>>>>>>>>>>>> proposed
> >>>>>>>>>>>>>>> in https://github.com/pharo-project/pharo/pull/1180.
> >>>>>>>>>>>>>>>
> >>>>>>>>>>>>>>>
> >>>>>>>>>>>>>>> Cheers,
> >>>>>>>>>>>>>>> Alistair
> >>>>>>>>>>>>>>>
> >>>>>>>>>>>>>>
> >>>>>>>>>>>>>> Hi,
> >>>>>>>>>>>>>> yes, if you are after universal behavior englobing Unix
> >>>>>>>>>>>>>> streams, the
> >>>>>>>>>>>>>> Exception might be the best way.
> >>>>>>>>>>>>>> Because on special stream you can't allways say in advance,
> you
> >>>>>>>>>>>>>> have to try.
> >>>>>>>>>>>>>> That's the solution adopted by authors of Xtreams.
> >>>>>>>>>>>>>> But there is a runtime penalty associated to it.
> >>>>>>>>>>>>>>
> >>>>>>>>>>>>>> The penalty once was so high that my proposal to generalize
> >>>>>>>>>>>>>> EndOfStream
> >>>>>>>>>>>>>> usage was rejected a few years ago by AndreaRaab.
> >>>>>>>>>>>>>> http://forum.world.st/EndOfStream-unused-td68806.html
> >>>>>>>>>>>>>
> >>>>>>>>>>>>> Thanks for this, I'll definitely take a look.
> >>>>>>>>>>>>>
> >>>>>>>>>>>>> Do you have a sense of how Denis' suggestion of using an
> >>>>>>>>>>>>> EndOfStream
> >>>>>>>>>>>>> object would compare?
> >>>>>>>>>>>>>
> >>>>>>>>>>>>> It would keep the same coding style, but avoid the problems
> with
> >>>>>>>>>>>>> nil.
> >>>>>>>>>>>>>
> >>>>>>>>>>>>> Thanks,
> >>>>>>>>>>>>> Alistair
> >>>>>>>>>>>>>
> >>>>>>>>>>>>>
> >>>>>>>>>>>>>
> >>>>>>>>>>>>>> I have regularly benched Xtreams, but stopped a few years
> ago.
> >>>>>>>>>>>>>> Maybe i can excavate and pass on newer VM.
> >>>>>>>>>>>>>>
> >>>>>>>>>>>>>> In the mean time, i had experimented a programmable end of
> >>>>>>>>>>>>>> stream behavior
> >>>>>>>>>>>>>> (via a block, or any other valuable)
> >>>>>>>>>>>>>> http://www.squeaksource.com/XTream.htm
> >>>>>>>>>>>>>> so as to reconcile performance and universality, but it was
> a
> >>>>>>>>>>>>>> source of
> >>>>>>>>>>>>>> complexification at implementation side.
> >>>>>>>>>>>>>>
> >>>>>>>>>>>>>> Nicolas
> >>>>>>>>>>>>>>
> >>>>>>>>>>>>>>>
> >>>>>>>>>>>>>>>
> >>>>>>>>>>>>>>>> Note also that a Guille introduced something new, #closed
> >>>>>>>>>>>>>>>> which is
> >>>>>>>>>>>>>>>> related to the difference between having no more elements
> >>>>>>>>>>>>>>>> (maybe right now,
> >>>>>>>>>>>>>>>> like an open network stream) and never ever being able to
> >>>>>>>>>>>>>>>> produce more data.
> >>>>>>>>>>>>>>>>
> >>>>>>>>>>>>>>>> Sven
> >>>>>>>>>>>>
> >>>>>>>>>>>>
> >>>>>>>>>>>
> >>>>>>>>>>
> >>>>>>>>>>
> >>>>>>>>>
> >>>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>> <stdio.cs>
> >
> >
>
>

Reply via email to