digitalmars.D - Streams: an open discussion
- Sean Kelly (41/41) Jun 09 2004 I think the D streams provide a good base but are missing some of the mo...
- Ben Hinkle (12/75) Jun 09 2004 It would be nice to have mixins DefaultInputStream and DefaultOutputStre...
- Sean Kelly (14/17) Jun 10 2004 What a wonderful idea :) I knew those mixins would come in handy for so...
- Ben Hinkle (23/44) Jun 10 2004 cool. That's usually the best way to gives ideas focus.
- Sean Kelly (41/62) Jun 11 2004 What bothered me about the exception throwing in Stream was that since a...
- Sean Kelly (2/2) Jun 11 2004 err... replace "template" with "class" in my example.
- Ben Hinkle (45/89) Jun 11 2004 says...
- Ben Hinkle (2/11) Jun 11 2004 oops - I forgot that Stream wants to implement InputStream and OutputStr...
- Sean Kelly (38/59) Jun 11 2004 It doesn't have to be quite so bad. I would probably do something like ...
- Arcane Jill (10/15) Jun 11 2004 I strongly disagree. Exceptions aren't just for errors, you know. There ...
- Derek (12/32) Jun 11 2004 But isn't this sort of like the 'bit' verses 'bool' thing. They are
- Andy Friesen (8/16) Jun 11 2004 If you think about it in terms of how many times the method is called
- Ben Hinkle (3/36) Jun 11 2004 Reaching the end of a file is not exceptional. Reaching the end of a fil...
- Sean Kelly (21/23) Jun 11 2004 If the user calls a function that expects a 4-byte chunk of data and the
- Sean Kelly (12/12) Jun 11 2004 Okay, I've been thinking about this and you're slowly winning me over. ...
- Ben Hinkle (16/49) Jun 11 2004 Looking at Stream.scanf it assumes one can read one character after the
- Sean Kelly (3/17) Jun 12 2004 Definately. I already made a similar change in getLine.
- The Dr ... who? (14/38) Jun 12 2004 All this stems from the fact that what is currently implemented, or what...
- Regan Heath (25/69) Jun 13 2004 Exactly.
- Sam McCall (17/40) Jun 13 2004 Is there a way in theory in general streams (sockets, files, anything
- Regan Heath (40/79) Jun 13 2004 In the case of stream sockets I reckon you're only 'at the end' if the
- Sam McCall (14/36) Jun 13 2004 Ouch. Presumably there are protocols where the socket gets closed with
- Regan Heath (17/53) Jun 13 2004 So unless the readLine function has a failure return value you have to
- Sam McCall (17/28) Jun 13 2004 But then how do you distinguish an empty line? My preferred behaviour
- Regan Heath (8/35) Jun 13 2004 shouldn't that be " "
- Sam McCall (4/5) Jun 13 2004 Sorry, those spaces were just meant to be for decoration, so it was
- Regan Heath (4/9) Jun 13 2004 I thought they *might* have been, just checking. :)
- Sean Kelly (18/31) Jun 14 2004 In general, yes. I would consider a socket at EOF when the socket is cl...
- Arcane Jill (44/52) Jun 11 2004 Not exactly. The difference between bool and bit is whether or not compi...
- Derek (5/73) Jun 11 2004 Got it. You are using Exceptions as a fancy GOTO.
- The Dr ... who? (29/99) Jun 12 2004 compile-time
- The Dr ... who? (16/110) Jun 12 2004 code).
- Derek (6/74) Jun 11 2004 Maybe I should think of Exceptions as Event Triggers instead of of Error
- Arcane Jill (48/57) Jun 12 2004 Exceptions are the most appropriate mechanism to use if the following fo...
- Sean Kelly (7/13) Jun 12 2004 Exception and Error are a good base, and we probably need BadCast, OutOf...
- Derek (11/34) Jun 12 2004 Thanks. This is quite a neat explanation. Maybe #2 could be reworded as ...
- Bent Rasmussen (12/12) Jun 13 2004 Is it an exception that the tenth element of a list does not exist when ...
- Antti =?iso-8859-1?Q?Syk=E4ri?= (17/27) Jun 14 2004 I'd have thought that exception handling in D and C++ have the same
- Matthew (10/29) Jun 14 2004 simple.
- J C Calvarese (9/35) Jun 21 2004 FYI, I think I found the thread you were remembering. It was called
- Sean Kelly (7/9) Jun 12 2004 They're an alternate means of flow control. Some argue that exceptions ...
- The Dr ... who? (41/95) Jun 12 2004 it
- Sam McCall (29/30) Jun 13 2004 And yet the way Java does does provide both mechanisms :-)
- Sam McCall (6/11) Jun 13 2004 Of course by "formatted" I meant data where we potentially assume some
- The Dr ... who? (15/30) Jun 12 2004 throw
- Walter (11/16) Jun 14 2004 unicode
- Arcane Jill (18/33) Jun 09 2004 As things stand, the Phobos documentation mentions almost none of this. ...
- Sean Kelly (8/30) Jun 10 2004 At this point, I think it's still better to just look at the Phobos sour...
- Sam McCall (13/26) Jun 13 2004 How well does Doxygen work with D? I've never used it, but love javadoc
- Kris (77/118) Jun 15 2004 Whoops! Posted this to the another thread, but I really meant to post he...
- surferjeff excite.com (12/12) Feb 25 2006 The interface for InputStream and OutputStream is huge. I often have to...
- Kyle Furlong (3/19) Feb 25 2006 Phobos sucks. There I said it. :-)
- Ben Hinkle (7/24) Feb 26 2006 Subclass Stream or FilterStream. You'll probably have to override 3 meth...
- surferjeff excite.com (8/34) Mar 15 2006 I see. Not so bad. Thanks.
- Sean Kelly (18/27) Mar 15 2006 Something like:
- Ben Hinkle (26/74) Mar 16 2006 Sure, one can trade-off flexibility and ease-of-use. For example
I think the D streams provide a good base but are missing some of the more complex features that I miss from C++, mostly to do with formatted i/o. This raises the rather large issue of localization which I'm going to ignore for the moment. As things stand, the basic D stream framework has an InputStream and OutputStream interface and then a single Stream class that implements both of these. File, MemoryStream, SliceStream, and BufferedStream all inherit from Stream, while BufferedFile inherits from BufferedStream. Stream and File do not buffer by default, BufferedStream acts as an adaptor class, and BufferedFile is the buffered version of the File stream class. Currently, all formatted i/o goes through the printf method, with the read/write methods offering unformatted i/o. There is also an OutBuffer class (though no corresponding InBuffer) which seems functionally similar to MemoryStream. I'd like separate InputStream, OutputStream, and Stream base classes to allow support for streams where only input or output makes sense. To make it clear these are base classes and prevent naming problems with the interfaces I propose these names: InputStreamBase, OutputStreamBase, and StreamBase (or InputOutputStreamBase, though that's pretty darn verbose). Because of the single inheritance rule, StreamBase won't be able to inherit from InputStreamBase and OutputStreamBase which will liekly result in some toying with the design to avoid code duplication. These classes will be obviously be abstract base classes. If I wanted to nit-pick I might suggest renaming File to FileStream for consistency. In addition to the existing functionality I propose new formatted i/o methods for all types that already have unformatted methods. Apart from a few instances these can forward most of the work to the existing printf method. The default methods would be "get" and "put" with the possibility of adding overloaded operator support in the future. I'd also like to see something similar to the callback mechanism in C++ streams so arbitrary classes can hook in formatting information. And Jill had mentioned wanting something similar to readsome() from C++ streams so I suspect this list will grow a bit. As for open issues, someone with more experience than myself should probably address localization. At the very least, there should be some support for proper numeric formatting, but that raises the issue of how formatting rules will be supplied to the stream classes and what else the localization rules should cover. I'm willing to go and do this myself, but as it's a modification of existing Phobos stuff I wanted to get some feedback. Does anyone have any objections or suggestions? Assuming the design doesn't suck will it have a chance for inclusion? Sean
Jun 09 2004
Sean Kelly wrote:I think the D streams provide a good base but are missing some of the more complex features that I miss from C++, mostly to do with formatted i/o. This raises the rather large issue of localization which I'm going to ignore for the moment. As things stand, the basic D stream framework has an InputStream and OutputStream interface and then a single Stream class that implements both of these. File, MemoryStream, SliceStream, and BufferedStream all inherit from Stream, while BufferedFile inherits from BufferedStream. Stream and File do not buffer by default, BufferedStream acts as an adaptor class, and BufferedFile is the buffered version of the File stream class. Currently, all formatted i/o goes through the printf method, with the read/write methods offering unformatted i/o. There is also an OutBuffer class (though no corresponding InBuffer) which seems functionally similar to MemoryStream. I'd like separate InputStream, OutputStream, and Stream base classes to allow support for streams where only input or output makes sense. To make it clear these are base classes and prevent naming problems with the interfaces I propose these names: InputStreamBase, OutputStreamBase, and StreamBase (or InputOutputStreamBase, though that's pretty darn verbose). Because of the single inheritance rule, StreamBase won't be able to inherit from InputStreamBase and OutputStreamBase which will liekly result in some toying with the design to avoid code duplication. These classes will be obviously be abstract base classes. If I wanted to nit-pick I might suggest renaming File to FileStream for consistency. In addition to the existing functionality I propose new formatted i/o methods for all types that already have unformatted methods. Apart from a few instances these can forward most of the work to the existing printf method. The default methods would be "get" and "put" with the possibility of adding overloaded operator support in the future. I'd also like to see something similar to the callback mechanism in C++ streams so arbitrary classes can hook in formatting information. And Jill had mentioned wanting something similar to readsome() from C++ streams so I suspect this list will grow a bit. As for open issues, someone with more experience than myself should probably address localization. At the very least, there should be some support for proper numeric formatting, but that raises the issue of how formatting rules will be supplied to the stream classes and what else the localization rules should cover. I'm willing to go and do this myself, but as it's a modification of existing Phobos stuff I wanted to get some feedback. Does anyone have any objections or suggestions? Assuming the design doesn't suck will it have a chance for inclusion? SeanIt would be nice to have mixins DefaultInputStream and DefaultOutputStream that would contain the default implementations from Stream and then Stream would be a mixin of those and the seeking and other odds and ends. That would make it easier to implement InputStream and OutputStream since users would just have to supply readBlock and writeBlock, respectively. So for example to define a FooInputStream class FooInputStream : InputStream { mixin DefaultInputStream; // ultimately call readBlock uint readBlock(...) {...} ... whatever else ... }
Jun 09 2004
In article <ca8kcl$1nvb$1 digitaldaemon.com>, Ben Hinkle says...It would be nice to have mixins DefaultInputStream and DefaultOutputStream that would contain the default implementations from Stream and then Stream would be a mixin of those and the seeking and other odds and ends.What a wonderful idea :) I knew those mixins would come in handy for something! I tend to develop ideas by coding so I've gone ahead and started the modifications. I decided to refactor the design a bit so the streams won't throw exceptions on eof() or on read errors. At the moment I'm going with having the streams castable to bit as an easy way to check state, much the same way C++ streams work. Otherwise the existing methods are staying pretty much as-is. I'll post more in a few days once I get more of the grunt work done. One question about character output. The docs say dchar is a 32-bit unicode character but I'm pretty sure that it's currently implemented as wchar_t in Windows right now (which would make it compatible with wchar). Is there any reason there shouldn't be methods to operate on all three char types: char, wchar, and dchar? Sean
Jun 10 2004
On Thu, 10 Jun 2004 23:35:52 +0000 (UTC), Sean Kelly <sean f4.ca> wrote:In article <ca8kcl$1nvb$1 digitaldaemon.com>, Ben Hinkle says...cool. That's usually the best way to gives ideas focus.It would be nice to have mixins DefaultInputStream and DefaultOutputStream that would contain the default implementations from Stream and then Stream would be a mixin of those and the seeking and other odds and ends.What a wonderful idea :) I knew those mixins would come in handy for something! I tend to develop ideas by coding so I've gone ahead and started the modifications.I decided to refactor the design a bit so the streams won't throw exceptions on eof() or on read errors.Are you talking about the ReadError in readExact? I think that error should stay since readBlock returns the number of bytes read if there isn't enough data. If one asks to read exactly 10 bytes and that is impossible it should throw an error.At the moment I'm going with having the streams castable to bit as an easy way to check state, much the same way C++ streams work.Two things come to mind: 1) Can opCast be implicit? The DMD spec says "Overloading the cast operator does not affect implicit casts, it only applies to explicit casts." Since writing cast(bit)foo isn't more readable than foo.eof() I'd stay away from opCast for bit. 2) if (foo) ... for any other object checks that foo is non-null. Making it anything else would be wierd.Otherwise the existing methods are staying pretty much as-is. I'll post more in a few days once I get more of the grunt work done.If you have time and/or desire check out the MmFile wrapper for streams that I mentioned on digitalmars.D.bugs available at http://home.comcast.net/~benhinkle/stream.d Down near the bottom there is ArrayStream(Buffer) that wraps "array-like" types with a stream API.One question about character output. The docs say dchar is a 32-bit unicode character but I'm pretty sure that it's currently implemented as wchar_t in Windows right now (which would make it compatible with wchar). Is there any reason there shouldn't be methods to operate on all three char types: char, wchar, and dchar?I wondered that, too, when I was poking around. It could be that stream.d came before dchar? I don't know. I haven't thought very much about it but adding dchar support seems reasonable to me. I can't think of any big reason not to.Sean
Jun 10 2004
In article <3i7ic0dlu2mdmb8q47bmvro8n4og30jvad 4ax.com>, Ben Hinkle says...On Thu, 10 Jun 2004 23:35:52 +0000 (UTC), Sean Kelly <sean f4.ca> wrote:What bothered me about the exception throwing in Stream was that since all methods are implemented in terms of readExact, an exception will always be throw when eof() is reached. In my opinion, end of file is an expected rather than an exceptional condition. If I had to wrap all my stream operations in try blocks I'd go nuts :)I decided to refactor the design a bit so the streams won't throw exceptions on eof() or on read errors.Are you talking about the ReadError in readExact? I think that error should stay since readBlock returns the number of bytes read if there isn't enough data. If one asks to read exactly 10 bytes and that is impossible it should throw an error.Darn. I'd forgotten about this. And I so liked the C++ semantics: while( istr.get(x) ); This would work if all operations returned a fail state, but it's much nicer to have them return the stream itself so operations can be chained. I suppose this works however: while( !istr.get(x).fail() ); and it is perhaps more clear.At the moment I'm going with having the streams castable to bit as an easy way to check state, much the same way C++ streams work.Two things come to mind: 1) Can opCast be implicit? The DMD spec says "Overloading the cast operator does not affect implicit casts, it only applies to explicit casts." Since writing cast(bit)foo isn't more readable than foo.eof() I'd stay away from opCast for bit.If you have time and/or desire check out the MmFile wrapper for streams that I mentioned on digitalmars.D.bugs available at http://home.comcast.net/~benhinkle/stream.d Down near the bottom there is ArrayStream(Buffer) that wraps "array-like" types with a stream API.Will do. I have to say, this lack of multiple inheritance has been interesting to deal with. As both InputStream and OutputStream share some common features (state tracking) it made sense to have them both inherit from a common interface. But as the IOStream class was to incorporate stuff from both of them this meant a diamond-shaped inheritance tree, which I think tosses the idea of having only two mixins. I haven't tested it, but assuming this code: class CommonBase { int x; } class DerivedA { mixin CommonBase; } template DerivedB { mixin CommonBase; } template Derived { mixin DerivedA; mixin DerivedB; } Derived will end up with two instances of x defined, won't it? Or perhaps a compiler error? Or is the code intelligent enough to gurantee that the stuff in CommonBase is only imported once? Sean
Jun 11 2004
err... replace "template" with "class" in my example. Sean
Jun 11 2004
"Sean Kelly" <sean f4.ca> wrote in message news:cacidg$1jn3$1 digitaldaemon.com...In article <3i7ic0dlu2mdmb8q47bmvro8n4og30jvad 4ax.com>, Ben Hinklesays...throwOn Thu, 10 Jun 2004 23:35:52 +0000 (UTC), Sean Kelly <sean f4.ca> wrote:What bothered me about the exception throwing in Stream was that since all methods are implemented in terms of readExact, an exception will always beI decided to refactor the design a bit so the streams won't throw exceptions on eof() or on read errors.Are you talking about the ReadError in readExact? I think that error should stay since readBlock returns the number of bytes read if there isn't enough data. If one asks to read exactly 10 bytes and that is impossible it should throw an error.when eof() is reached. In my opinion, end of file is an expected ratherthan anexceptional condition. If I had to wrap all my stream operations in tryblocksI'd go nuts :)Eof in the middle of reading an int (for example) shouldn't be expected, though. If one is trying to read an int and you only get half an int and a return value of false then every call to read(out int) will have to be wrapped in "if" tests instead of try-catches. Reading multiple values would look like if (!s.read(x1) || !s.read(x2) || !s.read(x3)) {evasive action} instead of try{ s.read(x1); s.read(x2); s.read(x3); } catch (ReadError re) { evasive action } Either way I think eof should be the "usual" way of checking if any data remains. [snip]I have to say, this lack of multiple inheritance has been interesting todealwith. As both InputStream and OutputStream share some common features(statetracking) it made sense to have them both inherit from a common interface.Butas the IOStream class was to incorporate stuff from both of them thismeant adiamond-shaped inheritance tree, which I think tosses the idea of havingonlytwo mixins. I haven't tested it, but assuming this code: class CommonBase { int x; } class DerivedA { mixin CommonBase; } template DerivedB { mixin CommonBase; } template Derived { mixin DerivedA; mixin DerivedB; } Derived will end up with two instances of x defined, won't it? Or perhapsacompiler error? Or is the code intelligent enough to gurantee that thestuff inCommonBase is only imported once?Is it possible to just have the mixins be the non-overlapping parts? I'm looking at Stream class and the routines that implement InputStream only call readBlock and eof to do their thing. I can't see any overlap with the implementations of OutputStream. In other words, lines 219-796 (plus line 209 for "readable") form DefaultInputStream and lines 802-932 (plus 210) form DefaultOutputStream. So I'm picturing interface InputStream{...} interface OutputStream {...} template DefaultInputStream() {...} template DefaultOutputStream() {...} class Stream { mixin DefaultInputStream; mixin DefaultOutputStream; ... } That way everything is backwards compatible with the existing stream.d. Users can't instantiate a DefaultInputStream by itself but that's ok.Sean
Jun 11 2004
interface InputStream{...} interface OutputStream {...} template DefaultInputStream() {...} template DefaultOutputStream() {...} class Stream { mixin DefaultInputStream; mixin DefaultOutputStream; ... }oops - I forgot that Stream wants to implement InputStream and OutputStream class Stream : InputStream, OutputStream {
Jun 11 2004
In article <cact25$2406$1 digitaldaemon.com>, Ben Hinkle says...Eof in the middle of reading an int (for example) shouldn't be expected, though.Agreed. But what about Eof as a result of reading a char?If one is trying to read an int and you only get half an int and a return value of false then every call to read(out int) will have to be wrapped in "if" tests instead of try-catches. Reading multiple values would look like if (!s.read(x1) || !s.read(x2) || !s.read(x3)) {evasive action} instead of try{ s.read(x1); s.read(x2); s.read(x3); } catch (ReadError re) { evasive action }It doesn't have to be quite so bad. I would probably do something like this: if( s.read(x1).read(x2).read(x3).fail() ) {evasive action} I admit this is a matter of preference, and there are certainly times when I want to throw an exception on read failure, but the fact that I don't *always* want an exception thrown makes me leery of building it into Stream. An alternative would be to allow the user to specify that he wants exceptions to be thrown by setting a flag.Either way I think eof should be the "usual" way of checking if any data remains.I agree. Part of my problem was that I didn't investigate how eof() worked until just now. Here's the call: bit eof() { return position() == size(); } This does allow for foreknowledge of eof() location (a feature I wasn't aware of), but it does this by scanning to the end of the stream and then resetting the read position. In some cases this operation can be quite expensive or just plain impossible. An alternative might be to specialize such classes to read-ahead by one byte on every read to check for eof(), but this will wreak havoc with streams that may block. I'm personally used to the method of the C read() function where it will return 0 on eof(), in which case the stream class would set an eof() flag and return a failure (or throw an exception I suppose). But this obviously eliminates any foreknowledge of when eof() has been reached, moving detection back into the read method. But again this is all my personal style and there may be a better way to do it (not to mention Mango, which follows yet another approach). The other consequence of my approach is that it isn't compatible with code written against the existing stream model, which is something I was hoping to avoid.Is it possible to just have the mixins be the non-overlapping parts? I'm looking at Stream class and the routines that implement InputStream only call readBlock and eof to do their thing. I can't see any overlap with the implementations of OutputStream.Definately. The overlap would only be new code and that could all be placed in a separate mixin. My question was as much academic as practical. I'm truly curious whether such a design would result in multiply defined data or not. In C/C++ I would say yes, but with D's module-level linkage model I'm not so sure.That way everything is backwards compatible with the existing stream.d. Users can't instantiate a DefaultInputStream by itself but that's ok.I'm kind of torn so far as backwards compatibility is concerned. There are things I don't like about the original design, but at the same time I don't want to propose yet another API format. However, the differences truly aren't that great so I'm going to go with them for now and see how they turn out. I admit I'm using this as an excuse to become more familiar with the language as much as to add features to the stream lib, so whatever happens I won't consider it a wasted effort. Sean
Jun 11 2004
In article <cacidg$1jn3$1 digitaldaemon.com>, Sean Kelly says...What bothered me about the exception throwing in Stream was that since all methods are implemented in terms of readExact, an exception will always be throw when eof() is reached. In my opinion, end of file is an expected rather than an exceptional condition. If I had to wrap all my stream operations in try blocks I'd go nuts :)I strongly disagree. Exceptions aren't just for errors, you know. There are all SORTS of non-error uses for exceptions. Just because something is expected, doesn't mean that an exception is not the best mechanism. Maybe I'm just more comfortable working with exceptions than some. To my mind, best practice behavior is to throw an exception on end-of-file, and a /different/ exception on error. I like this way of working. It beats the hell out of having to test the return value all the time. Arcane Jill
Jun 11 2004
On Fri, 11 Jun 2004 19:46:47 +0000 (UTC), Arcane Jill wrote:In article <cacidg$1jn3$1 digitaldaemon.com>, Sean Kelly says...But isn't this sort of like the 'bit' verses 'bool' thing. They are different animals but a 'bit' can be used to simulate a 'bool'. Likewise, reaching the end of file is not an exceptional event, in fact it is quite normal in most cases involving stream files. So although one can use the D exception mechanism to handle eof, the eof event is not really an exception. I know this just semantics, but ... must we be forced into using exceptions to handle eof, just like we are forced to use 'bit' to handle 'bool'? -- Derek Melbourne, AustraliaWhat bothered me about the exception throwing in Stream was that since all methods are implemented in terms of readExact, an exception will always be throw when eof() is reached. In my opinion, end of file is an expected rather than an exceptional condition. If I had to wrap all my stream operations in try blocks I'd go nuts :)I strongly disagree. Exceptions aren't just for errors, you know. There are all SORTS of non-error uses for exceptions. Just because something is expected, doesn't mean that an exception is not the best mechanism. Maybe I'm just more comfortable working with exceptions than some. To my mind, best practice behavior is to throw an exception on end-of-file, and a /different/ exception on error. I like this way of working. It beats the hell out of having to test the return value all the time. Arcane Jill
Jun 11 2004
Derek wrote:But isn't this sort of like the 'bit' verses 'bool' thing. They are different animals but a 'bit' can be used to simulate a 'bool'. Likewise, reaching the end of file is not an exceptional event, in fact it is quite normal in most cases involving stream files. So although one can use the D exception mechanism to handle eof, the eof event is not really an exception. I know this just semantics, but ... must we be forced into using exceptions to handle eof, just like we are forced to use 'bit' to handle 'bool'?If you think about it in terms of how many times the method is called and what fraction of those calls will be a read past the end of the stream, it doesn't seem too much of a stretch to call hitting EOF "exceptional". Further, this model ensures that, unlike C stdio, forgetting to check EOF causes reliable, reproducable behaviour. -- andy
Jun 11 2004
Derek wrote:On Fri, 11 Jun 2004 19:46:47 +0000 (UTC), Arcane Jill wrote:Reaching the end of a file is not exceptional. Reaching the end of a file before expected is exceptional.In article <cacidg$1jn3$1 digitaldaemon.com>, Sean Kelly says...But isn't this sort of like the 'bit' verses 'bool' thing. They are different animals but a 'bit' can be used to simulate a 'bool'. Likewise, reaching the end of file is not an exceptional event, in fact it is quite normal in most cases involving stream files. So although one can use the D exception mechanism to handle eof, the eof event is not really an exception. I know this just semantics, but ... must we be forced into using exceptions to handle eof, just like we are forced to use 'bit' to handle 'bool'?What bothered me about the exception throwing in Stream was that since all methods are implemented in terms of readExact, an exception will always be throw when eof() is reached. In my opinion, end of file is an expected rather than an exceptional condition. If I had to wrap all my stream operations in try blocks I'd go nuts :)I strongly disagree. Exceptions aren't just for errors, you know. There are all SORTS of non-error uses for exceptions. Just because something is expected, doesn't mean that an exception is not the best mechanism. Maybe I'm just more comfortable working with exceptions than some. To my mind, best practice behavior is to throw an exception on end-of-file, and a /different/ exception on error. I like this way of working. It beats the hell out of having to test the return value all the time. Arcane Jill
Jun 11 2004
In article <caddo3$2spa$1 digitaldaemon.com>, Ben Hinkle says...Reaching the end of a file is not exceptional. Reaching the end of a file before expected is exceptional.If the user calls a function that expects a 4-byte chunk of data and the function hits eof() after 2 bytes then the stream did not behave in an expected manner. Whether this is sufficiently bad to be worth an exception is really a matter of opinion, and no one agrees on how exceptions should be used anyway. Between what you and Andy said however, I'm inclined to agree that an exception may be warranted to protect the uncautious user from weird errors, even if I might not like the behavior myself :) How about this: if the stream expects a fixed-size chunk >1 byte and hits eof() before reading the expected number of bytes then it throws an exception. If the stream expects only 1 byte and hits eof() (ie. the read failed entirely) then it sets a failure state and returns without throwing. The only thing about this tactic that worries me is that it seems inconsistent and thus confusing. Here's an alternate: the unformatted read functions will throw an exception on eof() while the formatted read functions will not. The assumption being that if a programmer is using the unformatted functions then he's likely reading a data file with a known format and any violations of that format would be exceptional. If the programmer really wants to check for eof() to avoid this problem he could do: if( istr.peek().eof() ) Sean
Jun 11 2004
Okay, I've been thinking about this and you're slowly winning me over. I do write a lot of code like this: if( !istr.read( x ) ) throw new MyError(); and it would make a lot more sense to just expect the stream itself to do it. But I'm still on the fence with the end of file issue. If eof() can always be evaluated proactively (ie. so I can test for it when I need to and thus avoid an exception) then I'd say let's go ahead and throw excpetions on eof() during a read. The C functions have the eof() function, and I think in Windows I can call ReadFile with a read length of 0. Sockets can return closed status. What about other streams like USB ports and such? Darn, I think I've just been convinced ;) Sean
Jun 11 2004
Sean Kelly wrote:In article <caddo3$2spa$1 digitaldaemon.com>, Ben Hinkle says...readBlock is an option - though not at convenient.Reaching the end of a file is not exceptional. Reaching the end of a file before expected is exceptional.If the user calls a function that expects a 4-byte chunk of data and the function hits eof() after 2 bytes then the stream did not behave in an expected manner. Whether this is sufficiently bad to be worth an exception is really a matter of opinion, and no one agrees on how exceptions should be used anyway. Between what you and Andy said however, I'm inclined to agree that an exception may be warranted to protect the uncautious user from weird errors, even if I might not like the behavior myself :) How about this: if the stream expects a fixed-size chunk >1 byte and hits eof() before reading the expected number of bytes then it throws an exception. If the stream expects only 1 byte and hits eof() (ie. the read failed entirely) then it sets a failure state and returns without throwing. The only thing about this tactic that worries me is that it seems inconsistent and thus confusing.Here's an alternate: the unformatted read functions will throw an exception on eof() while the formatted read functions will not. The assumption being that if a programmer is using the unformatted functions then he's likely reading a data file with a known format and any violations of that format would be exceptional. If the programmer really wants to check for eof() to avoid this problem he could do: if( istr.peek().eof() )Looking at Stream.scanf it assumes one can read one character after the field being read. For example, the code to parse "%d" is while (isdigit(c) && width) { n = n * 10 + (c - '0'); width--; c = getc(); count++; } and getc() will throw an exception at eof(). That looks like a bug in scanf. I haven't tried any example, though, so I could just be reading the code incorrectly. It would be a little more involved to check for eof but the code would be more robust. Do you think that is a reasonable set of changes to make?Sean
Jun 11 2004
In article <cadj30$2b2$1 digitaldaemon.com>, Ben Hinkle says...Looking at Stream.scanf it assumes one can read one character after the field being read. For example, the code to parse "%d" is while (isdigit(c) && width) { n = n * 10 + (c - '0'); width--; c = getc(); count++; } and getc() will throw an exception at eof(). That looks like a bug in scanf. I haven't tried any example, though, so I could just be reading the code incorrectly. It would be a little more involved to check for eof but the code would be more robust. Do you think that is a reasonable set of changes to make?Definately. I already made a similar change in getLine. Sean
Jun 12 2004
All this stems from the fact that what is currently implemented, or what is being proposed, - pardon my ignorance of both - is a stream for all seasons. The times - all too many - I've written such things in the past I've separated an exception-free, byte-only stream lower layer, upon which may be layered whatever else one wants: object-based streams, streams that'll read ints/doubles/etc., text streams (\r\n <=> \n), etc. Surely that's the way to go? "Sean Kelly" <sean f4.ca> wrote in message news:cadg1r$2vpf$1 digitaldaemon.com...In article <caddo3$2spa$1 digitaldaemon.com>, Ben Hinkle says...theReaching the end of a file is not exceptional. Reaching the end of a file before expected is exceptional.If the user calls a function that expects a 4-byte chunk of data and the function hits eof() after 2 bytes then the stream did not behave in an expected manner. Whether this is sufficiently bad to be worth an exception is really a matter of opinion, and no one agrees on how exceptions should be used anyway. Between what you and Andy said however, I'm inclined to agree that an exception may be warranted to protect the uncautious user from weird errors, even if I might not like the behavior myself :) How about this: if the stream expects a fixed-size chunk >1 byte and hits eof() before reading the expected number of bytes then it throws an exception. Ifstream expects only 1 byte and hits eof() (ie. the read failed entirely) thenitsets a failure state and returns without throwing. The only thing about this tactic that worries me is that it seems inconsistent and thus confusing. Here's an alternate: the unformatted read functions will throw an exception on eof() while the formatted read functions will not. The assumption being thatifa programmer is using the unformatted functions then he's likely reading a data file with a known format and any violations of that format would beexceptional.If the programmer really wants to check for eof() to avoid this problem hecoulddo: if( istr.peek().eof() ) Sean
Jun 12 2004
On Fri, 11 Jun 2004 19:03:36 -0400, Ben Hinkle <bhinkle4 juno.com> wrote:Derek wrote:Exactly. Here is an example of how I typically read a file in C: f = fopen("filename","r"); if (!f) ..error.. while(fgets(bf,BFSZ,f)) { ..do stuff.. } if (ferror(f)) ..error.. fclose(f); getting to the end of the file in the above is not an exception in my mind, it's something that will happen every time this code is executed. I'd only want exceptions when: - the file open failed - the read failed (device error etc - not end of file) Plus the last line read may/may not have the end of line char(s) this is not exceptional either IMO. Arcane Jill's compiler code example showing using them as flow control can still be implemented without an exception on end of file in the stream code. It can be done by manually throwing an exception in the compiler code when the read hits eof. IMO this is actually better as it explicitly shows you're doing it. Regan -- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/On Fri, 11 Jun 2004 19:46:47 +0000 (UTC), Arcane Jill wrote:Reaching the end of a file is not exceptional. Reaching the end of a file before expected is exceptional.In article <cacidg$1jn3$1 digitaldaemon.com>, Sean Kelly says...But isn't this sort of like the 'bit' verses 'bool' thing. They are different animals but a 'bit' can be used to simulate a 'bool'. Likewise, reaching the end of file is not an exceptional event, in fact it is quite normal in most cases involving stream files. So although one can use the D exception mechanism to handle eof, the eof event is not really an exception. I know this just semantics, but ... must we be forced into using exceptions to handle eof, just like we are forced to use 'bit' to handle 'bool'?What bothered me about the exception throwing in Stream was that since all methods are implemented in terms of readExact, an exception will always be throw when eof() is reached. In my opinion, end of file is an expected rather than an exceptional condition. If I had to wrap all my stream operations in try blocks I'd go nuts :)I strongly disagree. Exceptions aren't just for errors, you know. There are all SORTS of non-error uses for exceptions. Just because something is expected, doesn't mean that an exception is not the best mechanism. Maybe I'm just more comfortable working with exceptions than some. To my mind, best practice behavior is to throw an exception on end-of-file, and a /different/ exception on error. I like this way of working. It beats the hell out of having to test the return value all the time. Arcane Jill
Jun 13 2004
Regan Heath wrote:Exactly. Here is an example of how I typically read a file in C: f = fopen("filename","r"); if (!f) ..error.. while(fgets(bf,BFSZ,f)) { ..do stuff.. } if (ferror(f)) ..error.. fclose(f); getting to the end of the file in the above is not an exception in my mind, it's something that will happen every time this code is executed.Is there a way in theory in general streams (sockets, files, anything else) to test whether we've read the last byte, without blocking? If so, I think something along the lines of while(!f.eof) { bf=f.gets(BFSZ); ... } is likely clearer.I'd only want exceptions when: - the file open failed - the read failed (device error etc - not end of file)What if scanf was looking for a floating point number, and it got to 6.03E+ and then hit EOF? (Maybe that's legal, it's not the point ;-) I'm keen on the idea that in a well-formed set of data, no read call fails, it means (when reading data of a known format) you don't have to put tests for error codes in your main code, and exceptions only handle errors of one sort or another.Plus the last line read may/may not have the end of line char(s) this is not exceptional either IMO.Sure, readLine should accept EOF as an EOL without throwing. Sam
Jun 13 2004
On Mon, 14 Jun 2004 15:37:33 +1200, Sam McCall <tunah.d tunah.net> wrote:Regan Heath wrote:Exactly. Here is an example of how I typically read a file in C: f = fopen("filename","r"); if (!f) ..error.. while(fgets(bf,BFSZ,f)) { ..do stuff.. } if (ferror(f)) ..error.. fclose(f); getting to the end of the file in the above is not an exception in my mind, it's something that will happen every time this code is executed.Is there a way in theory in general streams (sockets, files, anything else) to test whether we've read the last byte, without blocking?In the case of stream sockets I reckon you're only 'at the end' if the socket has been closed, otherwise, there might be data to read now, or not, or some might come later. Same with COM ports, and probably USB ports also. Files are a little different as the data is all available as soon as you open it. So .eof for a file simply compares the read ptr position with the position of the end of the file. You can make stream sockets non-blocking in which case a read will return immediately. Same with COM ports and I assume USB ports also. Sockets are weird in that when they are closed by the other end you get told by 'select' that you can 'read'/'write' to/from the socket, and the actual read/write reports that it is closed. AFAIK there is no other way to tell if it's been closed.If so, I think something along the lines of while(!f.eof) { bf=f.gets(BFSZ); ... } is likely clearer.I was only giving my C style code, not suggesting a format for the D code, the D could look like this... { FileStream i; try { i = new FileStream(new File("a.txt",READ)); while(!i.eof()) { line = i.readLine(); ..do stuff.. } } catch (Exception e) { ..you can catch all exceptions here and decide what to do with each.. } finally { if (i) delete i; } } or something like that.I'd only want exceptions when: - the file open failed - the read failed (device error etc - not end of file)What if scanf was looking for a floating point number, and it got to 6.03E+ and then hit EOF? (Maybe that's legal, it's not the point ;-)This is different, and should throw an exception :)I'm keen on the idea that in a well-formed set of data, no read call fails, it means (when reading data of a known format) you don't have to put tests for error codes in your main code, and exceptions only handle errors of one sort or another.Agreed.I only mentioned this as I imagine it would be a common mistake to make. Regan. -- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/Plus the last line read may/may not have the end of line char(s) this is not exceptional either IMO.Sure, readLine should accept EOF as an EOL without throwing.
Jun 13 2004
Regan Heath wrote:In the case of stream sockets I reckon you're only 'at the end' if the socket has been closed, otherwise, there might be data to read now, or not, or some might come later. Same with COM ports, and probably USB ports also. ... You can make stream sockets non-blocking in which case a read will return immediately. Same with COM ports and I assume USB ports also. Sockets are weird in that when they are closed by the other end you get told by 'select' that you can 'read'/'write' to/from the socket, and the actual read/write reports that it is closed. AFAIK there is no other way to tell if it's been closed.Ouch. Presumably there are protocols where the socket gets closed with no advance warning in the normal course of events (HTTP?). The tricky case seems to be: data\n<EOF> If you're reading data one line at a time from an unbuffered socket, and it ends like that, then you'll terminate by reading an EOF when you expected a line, and you can't predict it. It's frustrating, because it seems in every other case you can get away with using exceptions without having to handle them in non-error situations.Right, the point being that now hitting EOF during a read (well, at the beginning of a read, allowing no EOL at EOF) _is_ an exceptional circumstance. SamIf so, I think something along the lines of while(!f.eof) { bf=f.gets(BFSZ); ... } is likely clearer.I was only giving my C style code, not suggesting a format for the D code, the D could look like this...
Jun 13 2004
On Mon, 14 Jun 2004 16:31:31 +1200, Sam McCall <tunah.d tunah.net> wrote:Regan Heath wrote:In the case of stream sockets I reckon you're only 'at the end' if the socket has been closed, otherwise, there might be data to read now, or not, or some might come later. Same with COM ports, and probably USB ports also. ... You can make stream sockets non-blocking in which case a read will return immediately. Same with COM ports and I assume USB ports also. Sockets are weird in that when they are closed by the other end you get told by 'select' that you can 'read'/'write' to/from the socket, and the actual read/write reports that it is closed. AFAIK there is no other way to tell if it's been closed.Ouch. Presumably there are protocols where the socket gets closed with no advance warning in the normal course of events (HTTP?).HTTP sends a Content-Length most/all? of the time.The tricky case seems to be: data\n<EOF> If you're reading data one line at a time from an unbuffered socket, and it ends like that, then you'll terminate by reading an EOF when you expected a line, and you can't predict it.So unless the readLine function has a failure return value you have to throw an exception. The same would have to be true for readInt readFloat etc. If it had a failure return value then.. while(!i.eof()) { line = i.readLine(); if (line.length == 0) continue; } would work, as the readLine that read the EOF would flag eof and i.eof would then return true.It's frustrating, because it seems in every other case you can get away with using exceptions without having to handle them in non-error situations.Yeah.. I have felt this frustration before as I briefly tried to write my own stream lib, just for fun.If so, I think something along the lines of while(!f.eof) { bf=f.gets(BFSZ); ... } is likely clearer.I was only giving my C style code, not suggesting a format for the D code, the D could look like this...Right, the point being that now hitting EOF during a read (well, at the beginning of a read, allowing no EOL at EOF) _is_ an exceptional circumstance.Yep. -- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
Jun 13 2004
Regan Heath wrote:HTTP sends a Content-Length most/all? of the time.Not all the time :-(So unless the readLine function has a failure return value you have to throw an exception. The same would have to be true for readInt readFloat etc. If it had a failure return value then.. while(!i.eof()) { line = i.readLine(); if (line.length == 0) continue; }But then how do you distinguish an empty line? My preferred behaviour would be something like data \n \n <EOF> ^ readLine() returns "data" data \n \n <EOF> ^ readLine() returns "" data \n \n <EOF> ^ readLine() returns "" data \n \n <EOF> ^ readLine() returns null (EOF already been hit) Sam
Jun 13 2004
On Mon, 14 Jun 2004 17:27:52 +1200, Sam McCall <tunah.d tunah.net> wrote:Regan Heath wrote:agreed.HTTP sends a Content-Length most/all? of the time.Not all the time :-(So unless the readLine function has a failure return value you have to throw an exception. The same would have to be true for readInt readFloat etc. If it had a failure return value then.. while(!i.eof()) { line = i.readLine(); if (line.length == 0) continue; }But then how do you distinguish an empty line? My preferred behaviour would be something like data \n \n <EOF> ^ readLine() returns "data"data \n \n <EOF> ^ readLine() returns ""shouldn't that be " "data \n \n <EOF> ^ readLine() returns ""shouldn't that be " "data \n \n <EOF> ^ readLine() returns null (EOF already been hit)you're right here. Regan. -- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
Jun 13 2004
Regan Heath wrote:shouldn't that be " "Sorry, those spaces were just meant to be for decoration, so it was clear what had and hadn't been read yet. Sam
Jun 13 2004
On Mon, 14 Jun 2004 17:35:35 +1200, Sam McCall <tunah.d tunah.net> wrote:Regan Heath wrote:I thought they *might* have been, just checking. :) -- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/shouldn't that be " "Sorry, those spaces were just meant to be for decoration, so it was clear what had and hadn't been read yet. Sam
Jun 13 2004
In article <caj6cj$254g$1 digitaldaemon.com>, Sam McCall says...Is there a way in theory in general streams (sockets, files, anything else) to test whether we've read the last byte, without blocking? If so, I think something along the lines of while(!f.eof) { bf=f.gets(BFSZ); ... } is likely clearer.In general, yes. I would consider a socket at EOF when the socket is closed. The ANSI C file API has an feof() function, and other file APIs typically have a way to determine this as well.This is what convinced me that exceptions made sense for stream operations. Encountering an unexpected EOF *is* an exceptional situation IMO. Other exceptional situations include unformatted operations that fail to read the desired block size (typically as a result of EOF), and formatted read operations that result in unparsable or incorrect data. Note that this includes instances where the user tries to read an integer from the keyboard and gets a letter instead. One thing I'm considering is adding overridable methods that handle these error conditions so derived classes can throw more meaningful exceptions. If it's Windows and a meaningful message can be pulled from the error code then the class should be able to include that information in the exception. Since different APIs have different ways of returning error information, it isn't really possible to put all of this in the base class. SeanI'd only want exceptions when: - the file open failed - the read failed (device error etc - not end of file)What if scanf was looking for a floating point number, and it got to 6.03E+ and then hit EOF?
Jun 14 2004
In article <1l01dqjpufkr1$.e32a6q1rqkxy.dlg 40tude.net>, Derek says...But isn't this sort of like the 'bit' verses 'bool' thing. They are different animals but a 'bit' can be used to simulate a 'bool'.Not exactly. The difference between bool and bit is whether or not compile-time error checking is possible for a certain class of error. The difference between exceptions and return-value-checking is RUN-TIME error checking (versus crashing, which is what would happen if you forgot to check the return code).Likewise, reaching the end of file is not an exceptional event, in fact it is quite normal in most cases involving stream files.Let me quote you something from "The C++ Programming Language 3rd Edition" by Bjarne Stroustrup (the creator of C++): "Can an event that happens most times a program is run be considered exceptional? Can an event that is planned for and handled be considered an error? The answer to both questions is yes. 'Exceptional' does not mean 'almost never happens' or 'disastrous'. It is better to think of an exception as meaning 'some part of the system couldn't do what it was asked to do'". Further on in the book, there is a whole section entitled Exceptions that are not Errors, in which he says: "If an exception is expected and caught so that it has no bad effects on the behavior of the program then how can it be an error? Only because the programmer thinks of it as an error and of the exception-handling mechanisms as tools for handling errors. Alternatively, one might think of the exception-handling mechanisms as simply another control structure". I have written code in which an exception signals success! And this was not because I'm completely mad (I refrain from comment on that point), but because it was a brilliantly elegant thing to do. So it is here. We've reached the end of the file - yippee - now let's roll up the stack and move onto the next bit of code. In D, we should be using exceptions even more than in C++, because the exception handling mechanism is much, much simpler and there is way less overhead. Walter has written some good stuff in the D manual about why exceptions are better than return codes in handling errors. He should probably have mentioned that this is also true for non-errors.I know this just semantics, but ... must we be forced into using exceptions to handle eof, just like we are forced to use 'bit' to handle 'bool'?I think you'll find it's the other way round. On the bit/bool question, non-arithmetic bool would have been the safer option, but we have not been offered them. On the exception versus check-the-return code question, you can code it either ways, but one way is MUCH safer than the other. If I wrote an API which /required/ that callers check the return value from some funtion, how long do you think it would be before someone forgot? Exceptions are the path of safety. I think people are just afraid of using them, that's all. Maybe because of unfamilairity, or they have come to associate the exception-mechanism with error-handling. To me, refusing to employ the exception-mechanism because it isn't an error is like refusing to use for-loops because it isn't an error. I would hate to have to go back to the tedious and error-prone methods of return-value-checking. New tools give us new and powerful techniques. We should use them, not be afraid of them. Arcane Jill
Jun 11 2004
On Fri, 11 Jun 2004 23:32:32 +0000 (UTC), Arcane Jill wrote:In article <1l01dqjpufkr1$.e32a6q1rqkxy.dlg 40tude.net>, Derek says...Got it. You are using Exceptions as a fancy GOTO. -- Derek Melbourne, AustraliaBut isn't this sort of like the 'bit' verses 'bool' thing. They are different animals but a 'bit' can be used to simulate a 'bool'.Not exactly. The difference between bool and bit is whether or not compile-time error checking is possible for a certain class of error. The difference between exceptions and return-value-checking is RUN-TIME error checking (versus crashing, which is what would happen if you forgot to check the return code).Likewise, reaching the end of file is not an exceptional event, in fact it is quite normal in most cases involving stream files.Let me quote you something from "The C++ Programming Language 3rd Edition" by Bjarne Stroustrup (the creator of C++): "Can an event that happens most times a program is run be considered exceptional? Can an event that is planned for and handled be considered an error? The answer to both questions is yes. 'Exceptional' does not mean 'almost never happens' or 'disastrous'. It is better to think of an exception as meaning 'some part of the system couldn't do what it was asked to do'". Further on in the book, there is a whole section entitled Exceptions that are not Errors, in which he says: "If an exception is expected and caught so that it has no bad effects on the behavior of the program then how can it be an error? Only because the programmer thinks of it as an error and of the exception-handling mechanisms as tools for handling errors. Alternatively, one might think of the exception-handling mechanisms as simply another control structure". I have written code in which an exception signals success! And this was not because I'm completely mad (I refrain from comment on that point), but because it was a brilliantly elegant thing to do. So it is here. We've reached the end of the file - yippee - now let's roll up the stack and move onto the next bit of code. In D, we should be using exceptions even more than in C++, because the exception handling mechanism is much, much simpler and there is way less overhead. Walter has written some good stuff in the D manual about why exceptions are better than return codes in handling errors. He should probably have mentioned that this is also true for non-errors.I know this just semantics, but ... must we be forced into using exceptions to handle eof, just like we are forced to use 'bit' to handle 'bool'?I think you'll find it's the other way round. On the bit/bool question, non-arithmetic bool would have been the safer option, but we have not been offered them. On the exception versus check-the-return code question, you can code it either ways, but one way is MUCH safer than the other. If I wrote an API which /required/ that callers check the return value from some funtion, how long do you think it would be before someone forgot? Exceptions are the path of safety. I think people are just afraid of using them, that's all. Maybe because of unfamilairity, or they have come to associate the exception-mechanism with error-handling. To me, refusing to employ the exception-mechanism because it isn't an error is like refusing to use for-loops because it isn't an error. I would hate to have to go back to the tedious and error-prone methods of return-value-checking. New tools give us new and powerful techniques. We should use them, not be afraid of them. Arcane Jill
Jun 11 2004
"Derek" <derek psyc.ward> wrote in message news:c5k4ima3f0tp.1nm5clznwf9x6.dlg 40tude.net...On Fri, 11 Jun 2004 23:32:32 +0000 (UTC), Arcane Jill wrote:compile-timeIn article <1l01dqjpufkr1$.e32a6q1rqkxy.dlg 40tude.net>, Derek says...But isn't this sort of like the 'bit' verses 'bool' thing. They are different animals but a 'bit' can be used to simulate a 'bool'.Not exactly. The difference between bool and bit is whether or notbetweenerror checking is possible for a certain class of error. The differenceaexceptions and return-value-checking is RUN-TIME error checking (versus crashing, which is what would happen if you forgot to check the return code).Likewise, reaching the end of file is not an exceptional event, in fact it is quite normal in most cases involving stream files.Let me quote you something from "The C++ Programming Language 3rd Edition" by Bjarne Stroustrup (the creator of C++): "Can an event that happens most timesandprogram is run be considered exceptional? Can an event that is planned forbetterhandled be considered an error? The answer to both questions is yes. 'Exceptional' does not mean 'almost never happens' or 'disastrous'. It isitto think of an exception as meaning 'some part of the system couldn't do whatitwas asked to do'". Further on in the book, there is a whole section entitled Exceptions that are not Errors, in which he says: "If an exception is expected and caught so thaterror?has no bad effects on the behavior of the program then how can it be anoneOnly because the programmer thinks of it as an error and of the exception-handling mechanisms as tools for handling errors. Alternatively,becausemight think of the exception-handling mechanisms as simply another control structure". I have written code in which an exception signals success! And this was not because I'm completely mad (I refrain from comment on that point), butendit was a brilliantly elegant thing to do. So it is here. We've reached theofof the file - yippee - now let's roll up the stack and move onto the next bitexceptioncode. In D, we should be using exceptions even more than in C++, because thementionedhandling mechanism is much, much simpler and there is way less overhead. Walter has written some good stuff in the D manual about why exceptions are better than return codes in handling errors. He should probably havesomethat this is also true for non-errors.I know this just semantics, but ... must we be forced into using exceptions to handle eof, just like we are forced to use 'bit' to handle 'bool'?I think you'll find it's the other way round. On the bit/bool question, non-arithmetic bool would have been the safer option, but we have not been offered them. On the exception versus check-the-return code question, you can code it either ways, but one way is MUCH safer than the other. If I wrote an API which /required/ that callers check the return value fromarefuntion, how long do you think it would be before someone forgot? Exceptionsshouldthe path of safety. I think people are just afraid of using them, that's all. Maybe because of unfamilairity, or they have come to associate the exception-mechanism with error-handling. To me, refusing to employ the exception-mechanism because it isn't an error is like refusing to use for-loops because it isn't an error. I would hate to have to go back to the tedious and error-prone methods of return-value-checking. New tools give us new and powerful techniques. WeWell said. This is something that is little recognised by proponents of exceptions-for-all. They are a goto, since they change the flow of control. Sure, they're vastly better than goto, since resource handling is automatic. But, it's still possible for flow of control to jump to an arbitrary location. The only difference is that the destination is limited to somewhere in the call stack, whereas with goto it's anywhere the label is located. But, before anyone thinks I'm anti-exceptions, I'm not. They're the absolute right answer for a significant minority of error-handling scenarios, and the winner of an even bigger minority (if not the majority) of other scenarioe. They're just not the right answer in all cases.use them, not be afraid of them. Arcane JillGot it. You are using Exceptions as a fancy GOTO.
Jun 12 2004
"The Dr ... who?" <thedr who.com> wrote in message news:cafvrc$kts$1 digitaldaemon.com..."Derek" <derek psyc.ward> wrote in message news:c5k4ima3f0tp.1nm5clznwf9x6.dlg 40tude.net...code).On Fri, 11 Jun 2004 23:32:32 +0000 (UTC), Arcane Jill wrote:compile-timeIn article <1l01dqjpufkr1$.e32a6q1rqkxy.dlg 40tude.net>, Derek says...But isn't this sort of like the 'bit' verses 'bool' thing. They are different animals but a 'bit' can be used to simulate a 'bool'.Not exactly. The difference between bool and bit is whether or notbetweenerror checking is possible for a certain class of error. The differenceexceptions and return-value-checking is RUN-TIME error checking (versus crashing, which is what would happen if you forgot to check the returnbyLikewise, reaching the end of file is not an exceptional event, in fact it is quite normal in most cases involving stream files.Let me quote you something from "The C++ Programming Language 3rd Edition"timesBjarne Stroustrup (the creator of C++): "Can an event that happens mostawhatandprogram is run be considered exceptional? Can an event that is planned forbetterhandled be considered an error? The answer to both questions is yes. 'Exceptional' does not mean 'almost never happens' or 'disastrous'. It isto think of an exception as meaning 'some part of the system couldn't doitarewas asked to do'". Further on in the book, there is a whole section entitled Exceptions thatthatnot Errors, in which he says: "If an exception is expected and caught soitbiterror?has no bad effects on the behavior of the program then how can it be anoneOnly because the programmer thinks of it as an error and of the exception-handling mechanisms as tools for handling errors. Alternatively,becausemight think of the exception-handling mechanisms as simply another control structure". I have written code in which an exception signals success! And this was not because I'm completely mad (I refrain from comment on that point), butendit was a brilliantly elegant thing to do. So it is here. We've reached theof the file - yippee - now let's roll up the stack and move onto the nextofcanexceptioncode. In D, we should be using exceptions even more than in C++, because thementionedhandling mechanism is much, much simpler and there is way less overhead. Walter has written some good stuff in the D manual about why exceptions are better than return codes in handling errors. He should probably havethat this is also true for non-errors.I know this just semantics, but ... must we be forced into using exceptions to handle eof, just like we are forced to use 'bit' to handle 'bool'?I think you'll find it's the other way round. On the bit/bool question, non-arithmetic bool would have been the safer option, but we have not been offered them. On the exception versus check-the-return code question, youExceptionssomecode it either ways, but one way is MUCH safer than the other. If I wrote an API which /required/ that callers check the return value fromfuntion, how long do you think it would be before someone forgot?areitthe path of safety. I think people are just afraid of using them, that's all. Maybe because of unfamilairity, or they have come to associate the exception-mechanism with error-handling. To me, refusing to employ the exception-mechanism becauseSure,shouldisn't an error is like refusing to use for-loops because it isn't an error. I would hate to have to go back to the tedious and error-prone methods of return-value-checking. New tools give us new and powerful techniques. WeWell said. This is something that is little recognised by proponents of exceptions-for-all. They are a goto, since they change the flow of control.use them, not be afraid of them. Arcane JillGot it. You are using Exceptions as a fancy GOTO.they're vastly better than goto, since resource handling is automatic._and_ because the destination is arbitrated at runtime, and (largely) under control of client code. It's a kind of publish-subscribe mechanism. But it's still a goto!
Jun 12 2004
On Fri, 11 Jun 2004 23:32:32 +0000 (UTC), Arcane Jill wrote:In article <1l01dqjpufkr1$.e32a6q1rqkxy.dlg 40tude.net>, Derek says...Maybe I should think of Exceptions as Event Triggers instead of of Error Conditions. This is helpful. -- Derek Melbourne, AustraliaBut isn't this sort of like the 'bit' verses 'bool' thing. They are different animals but a 'bit' can be used to simulate a 'bool'.Not exactly. The difference between bool and bit is whether or not compile-time error checking is possible for a certain class of error. The difference between exceptions and return-value-checking is RUN-TIME error checking (versus crashing, which is what would happen if you forgot to check the return code).Likewise, reaching the end of file is not an exceptional event, in fact it is quite normal in most cases involving stream files.Let me quote you something from "The C++ Programming Language 3rd Edition" by Bjarne Stroustrup (the creator of C++): "Can an event that happens most times a program is run be considered exceptional? Can an event that is planned for and handled be considered an error? The answer to both questions is yes. 'Exceptional' does not mean 'almost never happens' or 'disastrous'. It is better to think of an exception as meaning 'some part of the system couldn't do what it was asked to do'". Further on in the book, there is a whole section entitled Exceptions that are not Errors, in which he says: "If an exception is expected and caught so that it has no bad effects on the behavior of the program then how can it be an error? Only because the programmer thinks of it as an error and of the exception-handling mechanisms as tools for handling errors. Alternatively, one might think of the exception-handling mechanisms as simply another control structure". I have written code in which an exception signals success! And this was not because I'm completely mad (I refrain from comment on that point), but because it was a brilliantly elegant thing to do. So it is here. We've reached the end of the file - yippee - now let's roll up the stack and move onto the next bit of code. In D, we should be using exceptions even more than in C++, because the exception handling mechanism is much, much simpler and there is way less overhead. Walter has written some good stuff in the D manual about why exceptions are better than return codes in handling errors. He should probably have mentioned that this is also true for non-errors.I know this just semantics, but ... must we be forced into using exceptions to handle eof, just like we are forced to use 'bit' to handle 'bool'?I think you'll find it's the other way round. On the bit/bool question, non-arithmetic bool would have been the safer option, but we have not been offered them. On the exception versus check-the-return code question, you can code it either ways, but one way is MUCH safer than the other. If I wrote an API which /required/ that callers check the return value from some funtion, how long do you think it would be before someone forgot? Exceptions are the path of safety. I think people are just afraid of using them, that's all. Maybe because of unfamilairity, or they have come to associate the exception-mechanism with error-handling. To me, refusing to employ the exception-mechanism because it isn't an error is like refusing to use for-loops because it isn't an error. I would hate to have to go back to the tedious and error-prone methods of return-value-checking. New tools give us new and powerful techniques. We should use them, not be afraid of them. Arcane Jill
Jun 11 2004
In article <iqr9lefhimza$.1wolikdlbu2jm$.dlg 40tude.net>, Derek says...Maybe I should think of Exceptions as Event Triggers instead of of Error Conditions. This is helpful.Exceptions are the most appropriate mechanism to use if the following four conditions are simultaneously met: 1) You wish to be advised of a particular circumstance 2) More often than not, the circumstance will not happen 3) When it does happen, information that it has happened needs to be propogated back up the call stack 4) Failure to communicate information about the circumstance will result in bad or undefined behavior These conditions are completely met in the case of end-of-file. You wish to be advised of it; more often than not, a read won't result in eof; you need to propogate eof up the call stack; if you don't, undefined behaviour - possibly bang. Ergo - there is mechanism that is just right - the exception mechanism. An example might help. Imagine you're writing a compiler/parser for some new programming langage you've just invented. Your main loop might look something like this:void parseModule(Stream s) { for (;;) { parseNextDeclaration(s); } }Within parseNextDeclaration() you're going to have other similiar loops, things like parseNextStatement(), parseNextExpression(), parseNextIdentifier(), and so on. And way, way, WAY down the call-stack, you're going to want to read raw fixed size blocks of data. WIthout the exception mechanism, you'd have to change every single one of those functions from void to bool. You would have to check the return value of every single one of them, every single time, and make sure to return false if some lower-level function returned false. Apart from being tedious and error-prone, this is also going to slow your program down, because of all that overhead of checking return values over and over again. You shouldn't need to do it, because eof is a rare circumstance (rare in the sense that most reads will succeed - I don't mean to imply that most files don't end, obviously). By contrast, to execute a throw statement, the code which the D compiler generates for you merely has to (1) copy a value into the stack pointer, (2) switch, based on the type of the exception thrown, (3) execute a jump instruction. Now tell me which has the greater overhead? (Okay, if there are nested try blocks and/or auto class declarations, you may have to repeat that procedure a few times, once for each exception frame, but generally there will be WAY more stack frames than exception frames). (The efficiency argument doesn't hold true in C++, by the way. In C++, simply copying a new value into the stack pointer would be disastrous in C++ because there may be objects on the stack whose destructors need to be called. D is more sensible). So you've got the best of all worlds - efficiency; safety; clean code. My one complaint about D's exceptions is that there realy SHOULD be some standard ones in Phobos which we could reuse - things like EndOfFile, OutOfMemory, BadParameter, ReadError, Success, and so on, all in one module. They should be organized into a heirarchy which makes sense, so it becomes obvious which one to use/derive from. Constructors for these should be simple. You shouldn't need to supply a string to construct an EndOfFile, and so on. Arcane Jill
Jun 12 2004
In article <caeaju$162q$1 digitaldaemon.com>, Arcane Jill says...My one complaint about D's exceptions is that there realy SHOULD be some standard ones in Phobos which we could reuse - things like EndOfFile, OutOfMemory, BadParameter, ReadError, Success, and so on, all in one module. They should be organized into a heirarchy which makes sense, so it becomes obvious which one to use/derive from. Constructors for these should be simple. You shouldn't need to supply a string to construct an EndOfFile, and so on.Exception and Error are a good base, and we probably need BadCast, OutOfMemory, DivideByZero and some others if they don't already exist. Beyond that I think it's up to each module to define a set of errors that makes sense. I think I may change the Stream errors around a bit so they can include platform-specific information in the cases where it's applicable. Sean
Jun 12 2004
On Sat, 12 Jun 2004 07:16:14 +0000 (UTC), Arcane Jill wrote:In article <iqr9lefhimza$.1wolikdlbu2jm$.dlg 40tude.net>, Derek says...2) The circumstance has a low frequency of occurance, or is not expected to occur. Because it is quite possible that sometimes, *not* reaching EOF is an error. [snip]Maybe I should think of Exceptions as Event Triggers instead of of Error Conditions. This is helpful.Exceptions are the most appropriate mechanism to use if the following four conditions are simultaneously met: 1) You wish to be advised of a particular circumstance 2) More often than not, the circumstance will not happen 3) When it does happen, information that it has happened needs to be propogated back up the call stack 4) Failure to communicate information about the circumstance will result in bad or undefined behaviorSo you've got the best of all worlds - efficiency; safety; clean code. My one complaint about D's exceptions is that there realy SHOULD be some standard ones in Phobos which we could reuse - things like EndOfFile, OutOfMemory, BadParameter, ReadError, Success, and so on, all in one module. They should be organized into a heirarchy which makes sense, so it becomes obvious which one to use/derive from. Constructors for these should be simple. You shouldn't need to supply a string to construct an EndOfFile, and so on.Hmmm... I tend to agree. -- Derek Melbourne, Australia
Jun 12 2004
Is it an exception that the tenth element of a list does not exist when the previous nine did? This is case for contracts over exceptions: To catch bugs use contracts, to recover from exceptional state use exceptions. - It is predictable that the file will end, it is possible to check when it does. - It is predictable that at some time a user will type in an email address without the at-sign, it is possible to check when s/he does. - It is predictable that a programmer will create bugs, its often possible to check when s/he does. But my experience with streams in general is very limited, so I must be missing something very trivial because this use of exceptions practically lights up all warning lights to me.
Jun 13 2004
In article <caeaju$162q$1 digitaldaemon.com>, Arcane Jill wrote:(The efficiency argument doesn't hold true in C++, by the way. In C++, simply copying a new value into the stack pointer would be disastrous in C++ because there may be objects on the stack whose destructors need to be called. D is more sensible).I'd have thought that exception handling in D and C++ have the same overhead, because both have RAII classes and try-catch statements. (In typical well-written C++ program, though, unwinding the stack takes a bit longer, since RAII is also used for memory management.) Of course, that wouldn't matter, since typical exception handling time is still negligible if exception handling is used properly.My one complaint about D's exceptions is that there realy SHOULD be some standard ones in Phobos which we could reuse - things like EndOfFile, OutOfMemory, BadParameter, ReadError, Success, and so on, all in one module. They should be organized into a heirarchy which makes sense, so it becomes obvious which one to use/derive from. Constructors for these should be simple. You shouldn't need to supply a string to construct an EndOfFile, and so on.Gets my vote. I think Matthew Wilson had something in the works a few months ago? (I somehow find it amusing to have a language with standard exception called "Success". Certainly requires some guts to admit that success is an exceptional condition ;) No committee-designed language would ever be able to pull that off...) -Antti -- I will not be using Plan 9 in the creation of weapons of mass destruction to be used by nations other than the US.
Jun 14 2004
"Antti Sykäri" <jsykari gamma.hut.fi> wrote in message news:slrnccrqj5.3eo.jsykari pulu.hut.fi...In article <caeaju$162q$1 digitaldaemon.com>, Arcane Jill wrote:simple.(The efficiency argument doesn't hold true in C++, by the way. In C++, simply copying a new value into the stack pointer would be disastrous in C++ because there may be objects on the stack whose destructors need to be called. D is more sensible).I'd have thought that exception handling in D and C++ have the same overhead, because both have RAII classes and try-catch statements. (In typical well-written C++ program, though, unwinding the stack takes a bit longer, since RAII is also used for memory management.) Of course, that wouldn't matter, since typical exception handling time is still negligible if exception handling is used properly.My one complaint about D's exceptions is that there realy SHOULD be some standard ones in Phobos which we could reuse - things like EndOfFile, OutOfMemory, BadParameter, ReadError, Success, and so on, all in one module. They should be organized into a heirarchy which makes sense, so it becomes obvious which one to use/derive from. Constructors for these should beYes, we did come to an accord on the naming conventions. I have to admit, somewhat sheepishly, that I didn't write it down anywhere, trusting the newgroup archive. If someone with more time (or good form) than me wants to search last year's posts for "Exception", or maybe "Win32Exception", then I'm sure it'll be there. Perhaps once located it could be placed up there with all JC's other good stuff on the Wiki? Lenny LazybonesYou shouldn't need to supply a string to construct an EndOfFile, and so on.Gets my vote. I think Matthew Wilson had something in the works a few months ago?
Jun 14 2004
Matthew wrote:"Antti Sykäri" <jsykari gamma.hut.fi> wrote in message news:slrnccrqj5.3eo.jsykari pulu.hut.fi......FYI, I think I found the thread you were remembering. It was called "Exception naming conventions - Phobos, and third party libraries" (yay, for helpful thread subjects). http://www.digitalmars.com/drn-bin/wwwnews?D/15869 -- Justin (a/k/a jcc7) http://jcc_7.tripod.com/d/simple.My one complaint about D's exceptions is that there realy SHOULD be some standard ones in Phobos which we could reuse - things like EndOfFile, OutOfMemory, BadParameter, ReadError, Success, and so on, all in one module. They should be organized into a heirarchy which makes sense, so it becomes obvious which one to use/derive from. Constructors for these should beYes, we did come to an accord on the naming conventions. I have to admit, somewhat sheepishly, that I didn't write it down anywhere, trusting the newgroup archive. If someone with more time (or good form) than me wants to search last year's posts for "Exception", or maybe "Win32Exception", then I'm sure it'll be there. Perhaps once located it could be placed up there with all JC's other good stuff on the Wiki? Lenny LazybonesYou shouldn't need to supply a string to construct an EndOfFile, and so on.Gets my vote. I think Matthew Wilson had something in the works a few months ago?
Jun 21 2004
In article <iqr9lefhimza$.1wolikdlbu2jm$.dlg 40tude.net>, Derek says...Maybe I should think of Exceptions as Event Triggers instead of of Error Conditions. This is helpful.They're an alternate means of flow control. Some argue that exceptions can make a program difficult to read, but I think so long as everything is well-documented it's not an issue. They certainly beat wrapping every function call with error checking routines, and exception performance has gotten quite good even in C++ these past few years. Sean
Jun 12 2004
In article <1l01dqjpufkr1$.e32a6q1rqkxy.dlg 40tude.net>, Derek says...betterBut isn't this sort of like the 'bit' verses 'bool' thing. They are different animals but a 'bit' can be used to simulate a 'bool'.Not exactly. The difference between bool and bit is whether or not compile-time error checking is possible for a certain class of error. The difference between exceptions and return-value-checking is RUN-TIME error checking (versus crashing, which is what would happen if you forgot to check the return code).Likewise, reaching the end of file is not an exceptional event, in fact it is quite normal in most cases involving stream files.Let me quote you something from "The C++ Programming Language 3rd Edition" by Bjarne Stroustrup (the creator of C++): "Can an event that happens most times a program is run be considered exceptional? Can an event that is planned for and handled be considered an error? The answer to both questions is yes. 'Exceptional' does not mean 'almost never happens' or 'disastrous'. It isto think of an exception as meaning 'some part of the system couldn't do whatitwas asked to do'". Further on in the book, there is a whole section entitled Exceptions that are not Errors, in which he says: "If an exception is expected and caught so thatithas no bad effects on the behavior of the program then how can it be an error? Only because the programmer thinks of it as an error and of the exception-handling mechanisms as tools for handling errors. Alternatively, one might think of the exception-handling mechanisms as simply another control structure". I have written code in which an exception signals success! And this was not because I'm completely mad (I refrain from comment on that point), but because it was a brilliantly elegant thing to do.Maybe so. Can't see as how it's particularly apposite to this issue, other than it's reflective of your opinion on the subject.So it is here. We've reached the end of the file - yippee - now let's roll up the stack and move onto the next bitofcode. In D, we should be using exceptions even more than in C++, because theexceptionhandling mechanism is much, much simpler and there is way less overhead.No. D is not Java, which equally accords with your given criterion. D is a multi-paradigm language, just like C++. That, above all the nifty little syntax tricks and GC, is what will make it succeed. Exceptions are the absolute right answer in many circumstances. Exceptions are the absolute wrong answer in many other circumstances. And sometimes, there's justified equivocation. And sometimes - this time! - people are coming at the issue from the wrong angle. Reading objects, or even fundamentals whose .size >1, requires exception handling. Manipulating byte (or, I guess, ANSI char) streams does _not_ require exception handling, and in many instances is better off without it. So rather than trying to do something hideous like have the user supply a bExceptionsPlease parameter, why not simply do the obvious thing, and build an object-aware exception-throwing arbitrary type manipulating layer on top of a super simple byte-stream layer? It's not exactly like it's a new idea, and the benefits are legion. For a start, we can plug in different byte streams, sharing a common interface, when appropriate.Walter has written some good stuff in the D manual about why exceptions are better than return codes in handling errors. He should probably have mentioned that this is also true for non-errors.It's not black, and it's not white. Such statements as this are positively unhelpful to the community, and especially to neophyte/junior programmers. The world is rich, and there are few richer parts of SE than error-handling.someI know this just semantics, but ... must we be forced into using exceptions to handle eof, just like we are forced to use 'bit' to handle 'bool'?I think you'll find it's the other way round. On the bit/bool question, non-arithmetic bool would have been the safer option, but we have not been offered them. On the exception versus check-the-return code question, you can code it either ways, but one way is MUCH safer than the other. If I wrote an API which /required/ that callers check the return value fromfuntion, how long do you think it would be before someone forgot? Exceptionsarethe path of safety. I think people are just afraid of using them, that's all.That may be for some. For others it's the opposite: exceptions are touted as appropriate to all error-handling / return-indicating scenarios. But there are many experienced and erudite players that do not see exceptions as a panacea. They are the answer in most cases, but they are _not_ the answer in all.Maybe because of unfamilairity, or they have come to associate the exception-mechanism with error-handling. To me, refusing to employ the exception-mechanism because it isn't an error is like refusing to use for-loops because it isn't an error.That's true.I would hate to have to go back to the tedious and error-prone methods of return-value-checking.Horses for courses.New tools give us new and powerful techniques. We should use them, not be afraid of them.True. But we should also be confident to point out when the emporer's undies are visible. Anyway, back to the topic: let's have a two/multi-layer streaming architecture, and this whole issue is rendered moot. The added advantage is that we'll actually have a more elegant and extensible architecture to boot!
Jun 12 2004
The Dr ... who? wrote:No. D is not Java...And yet the way Java does does provide both mechanisms :-) How about this? abstract class Stream { // reads a byte and stores it in dest, returns false // (and stores -1?) on eof abstract bool read(out ubyte dest); // reads up to len bytes, returns number read, or -1 on eof int read(ubyte[] dest,int off,int len); int read(ubyte[] dest) { return read(dest,0,dest.length); } // Reads a formatted value and throws on eof // Anyone got a good short name for this? void readData(out ubyte b); void readData(out int i); ... // reads exactly len bytes, throws on eof void readFully(byte[] dest,int off,int len); void readFully(byte[] dest) { readFully(dest,0,dest.length); } } All methods throw an IOException of some sort when a "real" error occurs, EOFException (or just EOF) could be a subclass of this or not. Java puts the formatted value reading in a subclass DataInputStream that wraps an instance of InputStream, I'm not sure about the rationale behind this. Sam
Jun 13 2004
Sam McCall wrote:// Reads a formatted value and throws on eof // Anyone got a good short name for this? void readData(out ubyte b); void readData(out int i); ...Of course by "formatted" I meant data where we potentially assume some binary format rather than just treating it as a stream of bytes. The point being that you expect there to be data in this format, so EOF *is* exceptional. Sam
Jun 13 2004
"Arcane Jill" <Arcane_member pathlink.com> wrote in message news:cad277$2bun$1 digitaldaemon.com...In article <cacidg$1jn3$1 digitaldaemon.com>, Sean Kelly says...throwWhat bothered me about the exception throwing in Stream was that since all methods are implemented in terms of readExact, an exception will always beanwhen eof() is reached. In my opinion, end of file is an expected rather thanblocksexceptional condition. If I had to wrap all my stream operations in tryLOL! Glad to see someone else taking on the mantle of humility.I'd go nuts :)I strongly disagree. Exceptions aren't just for errors, you know. There are all SORTS of non-error uses for exceptions. Just because something is expected, doesn't mean that an exception is not the best mechanism. Maybe I'm just more comfortable working with exceptions than some.To my mind, best practice behavior is to throw an exception on end-of-file, and a /different/ exception on error.What about all the other minds, and their ways of conceptualising errors, return values + stream manipulation? Wrong, irrelevant, jejune?I like this way of working. It beats the hell out of having to test the return value all the time.So it does, most of the time. But "all"? Big statement that. Humbly mine -- The Dr. da-da-da-dum, da-da-da-dum, da-da-da-dum, daaah da-da-da-dum, da-da-da-dum, da-da-da-dum, daaah woo-ooooo
Jun 12 2004
"Sean Kelly" <sean f4.ca> wrote in message news:caar8o$28ba$1 digitaldaemon.com...One question about character output. The docs say dchar is a 32-bitunicodecharacter but I'm pretty sure that it's currently implemented as wchar_tinWindows right now (which would make it compatible with wchar). Is thereanyreason there shouldn't be methods to operate on all three char types:char,wchar, and dchar?dchar is 32 bits wchar is 16 bits char is 8 bits The stream methods should all operate on chars as UTF-8 streams. The conversion to/from Windows 'W' functions should come as the last step.
Jun 14 2004
In article <ca82sq$u9n$1 digitaldaemon.com>, Sean Kelly says...As things stand, the basic D stream framework has an InputStream and OutputStream interface and then a single Stream class that implements both of these. File, MemoryStream, SliceStream, and BufferedStream all inherit from Stream, while BufferedFile inherits from BufferedStream. Stream and File do not buffer by default, BufferedStream acts as an adaptor class, and BufferedFile is the buffered version of the File stream class. Currently, all formatted i/o goes through the printf method, with the read/write methods offering unformatted i/o. There is also an OutBuffer class (though no corresponding InBuffer) which seems functionally similar to MemoryStream.As things stand, the Phobos documentation mentions almost none of this. I didn't even know that file streams were unbuffered, or that the class BufferedStream even existed, until a few days ago when someone told me. Anyway, I'd want a function available() to be available in input streams. (Same as Java's java.io.InputStream). The implementation of this is /childs play/. It goes like this: In InputStream and Streamabstract uint available();In unbuffered streams:override uint available() { return 0; }In buffered streams:override uint available() { return numBytesRemainingInBuffer + s.available(); }where s is the underlying stream. (This is likely to be itself unbuffered, and so it's available() function is likely to return zero - but there will always be special cases, so it's best to assume not). As one special case, for example a string input stream could have available() return the remaining length of the string. In any case, the most important thing about available() is that it MUST NOT BLOCK. It doesn't matter if it underestimates, but it must never overestimate. Arcane Jill
Jun 09 2004
In article <ca90hu$2bgd$1 digitaldaemon.com>, Arcane Jill says...As things stand, the Phobos documentation mentions almost none of this. I didn't even know that file streams were unbuffered, or that the class BufferedStream even existed, until a few days ago when someone told me.At this point, I think it's still better to just look at the Phobos source code. There's a lot of stuff in there that's largely undocumented.Anyway, I'd want a function available() to be available in input streams. (Same as Java's java.io.InputStream). The implementation of this is /childs play/. It goes like this: In InputStream and StreamI was planning on adding available() to BufferedStream only, as it doesn't seem to make sense for an unbuffered stream class. I guess the alternative would be to document rules that unbuffered classes could follow, like return 0 if they don't know and -1 if at the end of file. Seanabstract uint available();In unbuffered streams:override uint available() { return 0; }In buffered streams:override uint available() { return numBytesRemainingInBuffer + s.available(); }where s is the underlying stream. (This is likely to be itself unbuffered, and so it's available() function is likely to return zero - but there will always be special cases, so it's best to assume not). As one special case, for example a string input stream could have available() return the remaining length of the string. In any case, the most important thing about available() is that it MUST NOT BLOCK. It doesn't matter if it underestimates, but it must never overestimate.
Jun 10 2004
Sean Kelly wrote:In article <ca90hu$2bgd$1 digitaldaemon.com>, Arcane Jill says...How well does Doxygen work with D? I've never used it, but love javadoc for the ability to get a clean, readable reference, even if there's no actual description text for things (I've got the source).As things stand, the Phobos documentation mentions almost none of this. I didn't even know that file streams were unbuffered, or that the class BufferedStream even existed, until a few days ago when someone told me.At this point, I think it's still better to just look at the Phobos source code. There's a lot of stuff in there that's largely undocumented.I was planning on adding available() to BufferedStream only, as it doesn't seem to make sense for an unbuffered stream class. I guess the alternative would be to document rules that unbuffered classes could follow, like return 0 if they don't know and -1 if at the end of file.If you make the contract for available() to return the number of bytes known to be available, which may be an underestimate, or -1 if we're known to be at end of file (which isn't guaranteed even if we are?), then returning zero is _always_ safe, and returning nonzero values is a performance thing that shouldn't be relied on in general. (Of course if some class like BufferedStream is documented to always return positive when not at EOF, and -1 when at EOF, then you can rely on this when you know you've got a BufferedStream) Sam
Jun 13 2004
Whoops! Posted this to the another thread, but I really meant to post here instead ... Perhaps you might consider checking out mango.io over at http://www.dsource.org/forums/viewtopic.php?t=148 ? Mango.io attempts to provide seamless integration of the following: -Buffered I/O for Files, Sockets etc -A variety of Readers and Writers for formatted IO, endian conversion, etc -Multiple reader/writers upon the same buffer -Tokens and Tokenizers for loosely formatted input (text lines, words, numbers, etc) -RegExp token wrapper -Chained operations -EOS checking is almost completely redundant (you rarely, if ever, need to check) -Both put/get and <</>> syntax -Bidi equivalent of std.outbuffer (can use Readers/Writers per usual) -Memory-mapped IO seamlessly overloads buffered IO -Class serialization (to file, network, etc) -CompositeIO framework for bracketing IO (such as commit semantics) -Simply mechanism to bind your own classes into Reader/Writer framework -Exceptions thrown for exceptional conditions (per discussion) -Printf wrapper -Mango.io has very little overhead, so it's *fast*. You can optionally enable array-slicing when using CompositeReader. Tokens are always sliced, but you can .dup them -Includes typical file management tools (FileProxy, FileConduit), file path manipulation (FilePath), etc -Includes an RFC 2396 compliant URI specification -Includes a simple Properties file reader -Usual stdio singletons -some <gasp> documentation! There's a bunch more stuff in there also. Mango.io has been pretty well beaten-up by three great guys since March, so it's quite stable and robust now. Sure, there's things in there that could use improvement, but it's a reasonable start. The design is somewhat reminiscent of Java NIO, but without all the hideous IO warts that Java IO was originally saddled with. I would contend that mango.io is dramatically cleaner than the Java design; but that wouldn't be too hard, now would it? <g> Mango.io is part of the Mango Tree, which currently includes these other modules: -exceptionally fast HTTP server (thanks mainly to D array slicing) -Java like servlet engine (mango.io was built with this in mind) -Log4J clone, including an HTML monitor/console for inspecting and setting log/debug status at runtime (plus Chainsaw integration -An HTTP client -some simple caching mechanisms, including virtual caching to disk. I invite you to take a look, and comment. It'd be great if we could turn mango.io into a truly excellent IO platform for D ... - Kris "Sean Kelly" <sean f4.ca> wrote in message news:ca82sq$u9n$1 digitaldaemon.com...I think the D streams provide a good base but are missing some of the more complex features that I miss from C++, mostly to do with formatted i/o.Thisraises the rather large issue of localization which I'm going to ignorefor themoment. As things stand, the basic D stream framework has an InputStream and OutputStream interface and then a single Stream class that implements bothofthese. File, MemoryStream, SliceStream, and BufferedStream all inheritfromStream, while BufferedFile inherits from BufferedStream. Stream and Filedo notbuffer by default, BufferedStream acts as an adaptor class, andBufferedFile isthe buffered version of the File stream class. Currently, all formattedi/ogoes through the printf method, with the read/write methods offeringunformattedi/o. There is also an OutBuffer class (though no corresponding InBuffer)whichseems functionally similar to MemoryStream. I'd like separate InputStream, OutputStream, and Stream base classes toallowsupport for streams where only input or output makes sense. To make itclearthese are base classes and prevent naming problems with the interfaces Iproposethese names: InputStreamBase, OutputStreamBase, and StreamBase (or InputOutputStreamBase, though that's pretty darn verbose). Because of the single inheritance rule, StreamBase won't be able to inherit from InputStreamBase and OutputStreamBase which will liekly result in sometoyingwith the design to avoid code duplication. These classes will beobviously beabstract base classes. If I wanted to nit-pick I might suggest renamingFile toFileStream for consistency. In addition to the existing functionality I propose new formatted i/omethodsfor all types that already have unformatted methods. Apart from a fewinstancesthese can forward most of the work to the existing printf method. Thedefaultmethods would be "get" and "put" with the possibility of adding overloaded operator support in the future. I'd also like to see something similar tothecallback mechanism in C++ streams so arbitrary classes can hook informattinginformation. And Jill had mentioned wanting something similar toreadsome()from C++ streams so I suspect this list will grow a bit. As for open issues, someone with more experience than myself shouldprobablyaddress localization. At the very least, there should be some support for proper numeric formatting, but that raises the issue of how formattingruleswill be supplied to the stream classes and what else the localizationrulesshould cover. I'm willing to go and do this myself, but as it's a modification ofexistingPhobos stuff I wanted to get some feedback. Does anyone have anyobjections orsuggestions? Assuming the design doesn't suck will it have a chance for inclusion? Sean
Jun 15 2004
The interface for InputStream and OutputStream is huge. I often have to create my own streambufs in C++, which only requires implementing about 5 methods. If I want to write my own class that implements InputStream, then I have to implement about 50 methods, and another 50 if I want to implement OutputStream too! It would useful if there were smaller interfaces. For example, a read() method and eof() for input, and that's it. Then have a util class that takes one of these small interfaces and implements the full 50 methods in the bigger interface. Yes, I could do this in my own code, but I think many people will have to re-invent this wheel in D, and each re-invention will be different and not interchangeable.
Feb 25 2006
surferjeff excite.com wrote:The interface for InputStream and OutputStream is huge. I often have to create my own streambufs in C++, which only requires implementing about 5 methods. If I want to write my own class that implements InputStream, then I have to implement about 50 methods, and another 50 if I want to implement OutputStream too! It would useful if there were smaller interfaces. For example, a read() method and eof() for input, and that's it. Then have a util class that takes one of these small interfaces and implements the full 50 methods in the bigger interface. Yes, I could do this in my own code, but I think many people will have to re-invent this wheel in D, and each re-invention will be different and not interchangeable.Phobos sucks. There I said it. :-) In other news, there is a library called Mango on www.dsource.org which you may find useful.
Feb 25 2006
<surferjeff excite.com> wrote in message news:dtribg$eui$1 digitaldaemon.com...The interface for InputStream and OutputStream is huge. I often have to create my own streambufs in C++, which only requires implementing about 5 methods. If I want to write my own class that implements InputStream, then I have to implement about 50 methods, and another 50 if I want to implement OutputStream too! It would useful if there were smaller interfaces. For example, a read() method and eof() for input, and that's it. Then have a util class that takes one of these small interfaces and implements the full 50 methods in the bigger interface. Yes, I could do this in my own code, but I think many people will have to re-invent this wheel in D, and each re-invention will be different and not interchangeable.Subclass Stream or FilterStream. You'll probably have to override 3 methods: readBlock, writeBlock and seek. The interfaces are primarily for users to restrict their API - not for library writers to shoe-horn their classes into. Look at any of the small stream classes in std.stream to get an idea how easy it is to do.
Feb 26 2006
In article <dtsbc3$1c8g$1 digitaldaemon.com>, Ben Hinkle says...<surferjeff excite.com> wrote in message news:dtribg$eui$1 digitaldaemon.com...I see. Not so bad. Thanks. Instead of the "Inherit 20 methods, implement 3 pure virtual methods" approach, how about "implement the same 3 pure virtual methods in an interface, pass the interface to a class that uses it to implement the 20 methods." I've used the former pattern a lot in C++, and have found it difficult to reuse. I recently learned the latter pattern in Objective-C and Cocoa, and have found it much easier to reuse.The interface for InputStream and OutputStream is huge. I often have to create my own streambufs in C++, which only requires implementing about 5 methods. If I want to write my own class that implements InputStream, then I have to implement about 50 methods, and another 50 if I want to implement OutputStream too! It would useful if there were smaller interfaces. For example, a read() method and eof() for input, and that's it. Then have a util class that takes one of these small interfaces and implements the full 50 methods in the bigger interface. Yes, I could do this in my own code, but I think many people will have to re-invent this wheel in D, and each re-invention will be different and not interchangeable.Subclass Stream or FilterStream. You'll probably have to override 3 methods: readBlock, writeBlock and seek. The interfaces are primarily for users to restrict their API - not for library writers to shoe-horn their classes into. Look at any of the small stream classes in std.stream to get an idea how easy it is to do.
Mar 15 2006
surferjeff excite.com wrote:I see. Not so bad. Thanks. Instead of the "Inherit 20 methods, implement 3 pure virtual methods" approach, how about "implement the same 3 pure virtual methods in an interface, pass the interface to a class that uses it to implement the 20 methods." I've used the former pattern a lot in C++, and have found it difficult to reuse. I recently learned the latter pattern in Objective-C and Cocoa, and have found it much easier to reuse.Something like: class MyStreamImpl() { void readBlock(); void writeBlock(); seek(); } class Stream( Impl ) { mixin Impl!() impl; alias impl.readBlock readBlock; alias impl.writeBlock writeBlock; alias impl.seek seek; ... } alias Stream!(MyStreamImpl) MyStream; Sean
Mar 15 2006
<surferjeff excite.com> wrote in message news:dvaupb$1ok0$1 digitaldaemon.com...In article <dtsbc3$1c8g$1 digitaldaemon.com>, Ben Hinkle says...Sure, one can trade-off flexibility and ease-of-use. For example std.stream.File could just implement the 3 pure virtual methods and then user code would write Stream file = new Stream(new File("foo.txt")); So the flexibility of multiple classes and interfaces results in user code having to do more to hook things up. There are many many ways to slice things up. At one point I posted a suggestion to have a Stream subclass that accepted delegates for the 3 methods and then one wouldn't have to write a class at all - one can just write 3 nested functions and pass those to the constructor. For example void foo() { char buf[100]; size_t readBlock(void* buffer, size_t size) { ... do something with buf ... } .. 2 more nested functions for writeBlock and seek ... Stream s = new DelegateStream(&readBlock, &writeBlock, &seek); ... use s as any other stream ... } but I don't recall that suggestion getting any lovin' so I dropped it. I think if you have concrete suggestions go ahead and post them, see what kind of response you get and based on the response make changes and submit them to Walter and see how things go. -Ben<surferjeff excite.com> wrote in message news:dtribg$eui$1 digitaldaemon.com...I see. Not so bad. Thanks. Instead of the "Inherit 20 methods, implement 3 pure virtual methods" approach, how about "implement the same 3 pure virtual methods in an interface, pass the interface to a class that uses it to implement the 20 methods." I've used the former pattern a lot in C++, and have found it difficult to reuse. I recently learned the latter pattern in Objective-C and Cocoa, and have found it much easier to reuse.The interface for InputStream and OutputStream is huge. I often have to create my own streambufs in C++, which only requires implementing about 5 methods. If I want to write my own class that implements InputStream, then I have to implement about 50 methods, and another 50 if I want to implement OutputStream too! It would useful if there were smaller interfaces. For example, a read() method and eof() for input, and that's it. Then have a util class that takes one of these small interfaces and implements the full 50 methods in the bigger interface. Yes, I could do this in my own code, but I think many people will have to re-invent this wheel in D, and each re-invention will be different and not interchangeable.Subclass Stream or FilterStream. You'll probably have to override 3 methods: readBlock, writeBlock and seek. The interfaces are primarily for users to restrict their API - not for library writers to shoe-horn their classes into. Look at any of the small stream classes in std.stream to get an idea how easy it is to do.
Mar 16 2006