Nicolas, You have some interesting observations re senders of #next: - fixing it is sounding like a good idea. Since you are not ready to take the plunge on #next, I will be forced to deprecate it for my own use and continue to use #nextOne, unless we take the pluggable exception route?? Stef, how should we proceed? I think this ultimately has to go to the board for a decision. For my part, I am happy to help, will gladly take advantage of whatever we fix, and will deprecate/add protocol to ensure correct behavior where we do not act. To summarize, the options appear to be: (1) add pluggable exceptions covering #next, #next:, etc.; any attempt to read off the end of a stream would invoke the set behavior, either an exception with teeth (no default action), or truncate/answer nil as appropriate. (2) Fix #next: on the grounds Nicolas has identified, specifically that many senders assume non-truncating behavior; #next would likely remain as-is. (3) Adopt Dolphin's behavior - I do not see us taking this branch, but list it for completeness. Either way, add #nextAvailable: - it is harmless to backward compatibility, so can go in in either case. Bill -----Original Message----- From: pharo-project-bounces@lists.gforge.inria.fr [mailto:pharo-project-bounces@lists.gforge.inria.fr] On Behalf Of Nicolas Cellier Sent: Tuesday, June 09, 2009 7:38 AM To: Pharo-project@lists.gforge.inria.fr Subject: Re: [Pharo-project] About EndOfStream notification [was Streams - #nextLine] 2009/6/9 Schwab,Wilhelm K <bschwab@anest.ufl.edu>:
Nicolas,
Adding #nextAvailable: hurts nothing, but changing #next: (and #next too) will break existing code. Â In VW, it is only #next that has the silent failure trap, and while Cincom was willing to consider a change, they ultimately declined to make it. Â I am convinced that Dolphin gets it right, but I would be surprised to see us adopt its behavior. Â I would be thrilled if we did so, but doubt it will happen. Â Failing such breaking changes, I need to create a way to have my code work, which is why I started adding my own methods.
That's the price to pay, we have to break some #next: senders... Inside the image, we can fix it easily. Bt how many should we fix? I have 18 implementors (16 stream-like, 2 linked-list like) and 100 senders in core, but when looking at them, few are prepared to get a shorter collection than requested. For example, I read: (self next: 1) at: 1 or: header := strm next: 4. self nSamples: header first nLevels: header second. self setAlpha: header third beta: header fourth. IMO, the change you request is a must in a majority of cases... It's of course better to see an immediate EndOfStreamError rather than a delayed OutOfBoundError. For external packages, either the change is backported to other Squeak branches on a collaborative basis (preferred), or we'll have to maintain Pharo specific code on a competitive basis. Other squeak branches don't need to adopt our #next: behaviour, they just have to provide a #nextAvailable: hook for compatibility, so I don't think this is a real problem, especially if it enhances portability. For #next, I can understand VW declined: 1) they would have to change a bunch of senders 2) they have to guarantee a certain degree of portability to their clients, especially on such a heavily used kernel method. In Squeak code too, there are just too many senders of #next, the transition would be painfull without some backward compatibility.
Your pluggable exception/defaultAction idea is worth a shot. Â Some simple testing should show whether it can preserve current behavior and throw exceptions, respectively. Â I think I heard Stef as much as say he would support it if it does serve both masters. Â Stef?
Bill
Cost is small. Think of adding a Nile compatible hook too.
-----Original Message----- From: pharo-project-bounces@lists.gforge.inria.fr [mailto:pharo-project-bounces@lists.gforge.inria.fr] On Behalf Of Nicolas Cellier Sent: Tuesday, June 09, 2009 2:34 AM To: Pharo-project@lists.gforge.inria.fr Subject: Re: [Pharo-project] About EndOfStream notification [was Streams - #nextLine]
Bill, What I propose is to let programmer decide whether he will use Exception or not on endOfStream. And if he choose Exception, I underline that a defaultAction answering nil is not a panacea. But that defaultAction would still be an option if it solves your problem.
Not sure my proposition does really solve the #next: problem you raised, indeed. The solution could be independant of endOfStream handling for this one. I support your request of creating a VW/Dolphin compatible #nextAvailable: and changing #next: to raise a NotEnoughElementAvailableError (maybe a subclass of EndOfStreamError). We would have a few package incompatibility, but, on ne fait pas d'omelette sans casser des oeufs...
But I'm not convinced by the idea of duplicating the whole method protocol. Nor on duplicating the whole Stream class hierarchy, it's too big. That's were a classic delegation pattern can help (pluggable endOfStream). Of course, Trait composition is another option, and dynamic (on the fly) composition would be fun experimenting (as opposed to Static class definition). Keeping Traits as independant code units as possible is an interesting challenge (to explore the limits of such design).
Nicolas
2009/6/9 Schwab,Wilhelm K <bschwab@anest.ufl.edu>:
On Jun 8, 2009, at 9:32 PM, Nicolas Cellier wrote:
There are better examples where I want Exceptions, so I'd like the choice to be in programmers hands. - 1) Raising an EndOfStream Exception (and not a Notification as I suggested) should be optional - 2) The Exception should not have a default action.
To add emphasis: it can't have a default action or it is not doing its job.
The simple thing to do is to add an endOfStreamAction instanceVariable to Stream or ReadStream. If a read past end is attempted, then ^endOfStreamAction value.
nil value = nil, so letting this inst var uninitialized will lead to backward compatibility (at minimal cost concerning efficieny!). filling the inst var with a block comes to mind immediately, and among natural choice is: Stream>>willSignalEndOfStream    self endOfStreamAction: [EndOfStream signal]
There might be more work for Stream wrappers, but that sounds a cheap and efficient idea to reconcile both worlds.
What will protect above code example from an internal low level EndOfStream? Nothing, but the fact that programmers using explicitely #willSignalEndOfStream will know what they do! Either they will protect with a handling block, or advertise enough that the code might generate spurious EndOfStream on malformed inputs...
I hesitate to call the exceptions spurious; in situations where they would be described as such, I generally would use #nextAvailable: and write code that won't blow up. Â Exceptions do a very important job: they carry information from the point of detection of a problem to a place (often far removed on the stack) where a corrective action can be reasonably applied.
To (attempt) to paraphrase your idea, you are proposing to remove the default action from EndOfStream, replacing that blunting of exceptions with an uninitialized endOfStreamAction instance variable that defalts to the same behavior, and can be set to ensure raising of exceptions. Â Fair?
This is certainly worth a try. Â For my part, the cost would be I need to ensure that I set the exception behavior on every stream I create vs. ensuring I use a different set of methods. Â It's probably no worse, and maybe easier to enforce. Â I will generally hide ReadStream on: behind a helper, #readStream, so I could just as easily use #readStreamRobust to create the stream and activate exceptions. Â Sorry to press this so hard, but I cannot afford to have things breaking w/o telling me. Â At best, that wastes time to track down mysterious failures, and worse, it can be dangerous. Â It's not unlike the practice of building electronic enclosures with lots of exposed grounded metal. Â It took me a while to gain comfort with it, but the idea is that if a wire comes loose, it hits ground, pulls a breaker, and goes into a safe mode and gets attention as a side effect.
Bill
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project