June 13, 2004 Re: Streams: an open discussion | ||||
---|---|---|---|---|
| ||||
Posted in reply to Arcane Jill | On Sat, 12 Jun 2004 07:16:14 +0000 (UTC), Arcane Jill wrote: > 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 Thanks. This is quite a neat explanation. Maybe #2 could be reworded as ... 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] > > 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. Hmmm... I tend to agree. -- Derek Melbourne, Australia |
June 13, 2004 Re: Streams: an open discussion | ||||
---|---|---|---|---|
| ||||
Posted in reply to The Dr ... who? | 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
|
June 13, 2004 Re: Streams: an open discussion | ||||
---|---|---|---|---|
| ||||
Posted in reply to Sean Kelly | Sean Kelly wrote: > 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. 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). > 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 |
June 13, 2004 Re: Streams: an open discussion | ||||
---|---|---|---|---|
| ||||
Posted in reply to Sam McCall | 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
|
June 13, 2004 Re: Streams: an open discussion | ||||
---|---|---|---|---|
| ||||
Posted in reply to Arcane Jill | 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. |
June 14, 2004 Re: Streams: an open discussion | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ben Hinkle | On Fri, 11 Jun 2004 19:03:36 -0400, Ben Hinkle <bhinkle4@juno.com> wrote: > Derek wrote: > >> On Fri, 11 Jun 2004 19:46:47 +0000 (UTC), Arcane Jill wrote: >> >>> 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 >> >> 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'? > > Reaching the end of a file is not exceptional. Reaching the end of a file > before expected is exceptional. 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/ |
June 14, 2004 Re: Streams: an open discussion | ||||
---|---|---|---|---|
| ||||
Posted in reply to Regan Heath | 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 |
June 14, 2004 Re: Streams: an open discussion | ||||
---|---|---|---|---|
| ||||
Posted in reply to Sam McCall | 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. >> 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. 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/ |
June 14, 2004 Re: Streams: an open discussion | ||||
---|---|---|---|---|
| ||||
Posted in reply to Regan Heath | 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. >> 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. Sam |
June 14, 2004 Re: Streams: an open discussion | ||||
---|---|---|---|---|
| ||||
Posted in reply to Sam McCall | 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/ |
Copyright © 1999-2021 by the D Language Foundation