June 12, 2004 Re: Streams: an open discussion | ||||
---|---|---|---|---|
| ||||
Posted in reply to Arcane Jill | On Fri, 11 Jun 2004 23:32:32 +0000 (UTC), Arcane Jill wrote: > 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 Maybe I should think of Exceptions as Event Triggers instead of of Error Conditions. This is helpful. -- Derek Melbourne, Australia |
June 12, 2004 Re: Streams: an open discussion | ||||
---|---|---|---|---|
| ||||
Posted in reply to Derek | 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 |
June 12, 2004 Re: Streams: an open discussion | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ben Hinkle | 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 |
June 12, 2004 Re: Streams: an open discussion | ||||
---|---|---|---|---|
| ||||
Posted in reply to Derek | 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 |
June 12, 2004 Re: Streams: an open discussion | ||||
---|---|---|---|---|
| ||||
Posted in reply to Arcane Jill | 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 |
June 12, 2004 Re: Streams: an open discussion | ||||
---|---|---|---|---|
| ||||
Posted in reply to Sean Kelly | 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... > > > >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 > > |
June 12, 2004 Re: Streams: an open discussion | ||||
---|---|---|---|---|
| ||||
Posted in reply to Arcane Jill | > 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. 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 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. 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. > >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. 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! |
June 12, 2004 Re: Streams: an open discussion | ||||
---|---|---|---|---|
| ||||
Posted in reply to Derek | "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: > > > 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 > > Got it. You are using Exceptions as a fancy GOTO. Well 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. |
June 12, 2004 Re: Streams: an open discussion | ||||
---|---|---|---|---|
| ||||
Posted in reply to Arcane Jill | "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... > > >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. LOL! Glad to see someone else taking on the mantle of humility. > 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 |
June 12, 2004 Re: Streams: an open discussion | ||||
---|---|---|---|---|
| ||||
Posted in reply to The Dr ... who? | "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... > > On Fri, 11 Jun 2004 23:32:32 +0000 (UTC), Arcane Jill wrote: > > > > > 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 > > > > Got it. You are using Exceptions as a fancy GOTO. > > Well 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. _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! |
Copyright © 1999-2021 by the D Language Foundation