Playing a bit devil's advocate, the idea is that, in general, [ stream atEnd] whileFalse: [ stream next. "..." ].
is no longer allowed ? And you want to replace it with [ stream next ifNil: [ false ] ifNotNil: [ :x | "..." true ] whileTrue. That is a pretty big change, no ? I think/feel like a proper EOF exception would be better, more correct. [ [ stream next. "..." true ] on: EOF do: [ false ] ] whileTrue. Will we throw away #atEnd then ? Do we need it if we cannot use it ? > 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