digitalmars.D - Change the name of ArrayBoundsException in druntime
- Jacob Carlborg (5/5) Oct 22 2008 I think the name ArrayBoundsException should be changed to a more
- Jarrett Billingsley (2/7) Oct 22 2008 2nded.
- Denis Koroskin (3/13) Oct 22 2008 Agreed. BTW, why it is not an Error but Exception?
- Sean Kelly (10/26) Oct 22 2008 The Error class was created shortly before release and I didn't get
- Jacob Carlborg (3/34) Oct 22 2008 Yes it's longer but I gave three suggestions. I just don't want Array in...
- Jason House (2/32) Oct 22 2008
- Sean Kelly (12/35) Oct 22 2008 Errors represent situations which are typically non-recoverable--program...
- Jarrett Billingsley (2/6) Oct 22 2008 How, pray tell, is an app supposed to recover from an out-of-memory cond...
- Sean Kelly (27/34) Oct 22 2008 By releasing dynamically allocated memory. I'd expect some to be
- Jarrett Billingsley (4/9) Oct 22 2008 I think that's probably a valid thing to try, and considered it after
- Bill Baxter (10/19) Oct 22 2008 I think a more common recoverable situation would be an app where user
- Jesse Phillips (6/49) Oct 22 2008 I think a good reason for keeping it an exception (ie recoverable) is
- Robert Fraser (13/57) Oct 23 2008 Didn't see this discussion before I went off my tirade. I agree it's
- Sean Kelly (11/24) Oct 23 2008 I'd argue that anyone who catches Exception, prints a message, and
- Robert Fraser (6/10) Oct 23 2008 I'm currently studying Computer Engineering at university. I don't think...
- Bill Baxter (6/17) Oct 23 2008 People do still develop for embedded devices with small memory and/or
- Robert Fraser (13/31) Oct 24 2008 I'm not saying it doesn't come up in practice; I'm saying developers are...
- Jesse Phillips (9/45) Oct 24 2008 The problem with it being an error is that the programmer has no way to
- Robert Fraser (12/58) Oct 25 2008 Sure there is:
- Jesse Phillips (5/71) Oct 25 2008 Oops, from past discussions about the difference I somehow got the idea
- Sean Kelly (10/29) Oct 31 2008 After some thought, I'm inclined to agree. While an OOM condition might...
- Denis Koroskin (10/47) Oct 23 2008 I think that OutOfMemoryException should *not* be recoverable. Instead, ...
- Andrei Alexandrescu (6/63) Oct 23 2008 But one of the best things possible to do is unwind the stack and fall
- Denis Koroskin (23/88) Oct 23 2008 You can do that, of course, just don't handle the onOutOfMemory custom
- Andrei Alexandrescu (8/106) Oct 23 2008 I understand your motivation. But you can easily implement all of that
- Sean Kelly (29/39) Oct 23 2008 This is a fair point, but how does one implement this safely? Let's say...
- Andrei Alexandrescu (4/47) Oct 23 2008 Perfectly put. Again: why prevent use of exceptions for the one case
- Sergey Gromov (5/12) Oct 23 2008 In an image editor, a user asks to create a huge image (50k x 50k). You...
- Andrei Alexandrescu (6/18) Oct 23 2008 I could extract many instances of this pattern from my programs.
- Sergey Gromov (5/23) Oct 23 2008 I've noticed that failed new sometimes simply returned null instead of
- Sean Kelly (4/8) Oct 23 2008 I think I've corrected all these in druntime. if I haven't please let
- Sergey Gromov (4/12) Oct 23 2008 I wasn't using druntime nor Tango when I stumbled upon that. I'm glad t...
- Robert Fraser (17/48) Oct 23 2008 Ah NOOOOO! Please don't make an out of memory catchable with a plain
- KennyTM~ (15/67) Oct 23 2008 Make OutOfMemoryException the own subclass of Throwable? Then we have
- Lars Kyllingstad (10/83) Oct 25 2008 Even though the last suggestion was partially meant as a joke, I think
- Sergey Gromov (4/8) Oct 23 2008 Maybe IndexingError ? There are not necessarily any bounds when you're
- Andrei Alexandrescu (3/12) Oct 23 2008 STL has range_error. I like that because it's rather general.
- Sean Kelly (4/16) Oct 31 2008 The terminology matches D's new range concept anyway, which is a nice
- Denis Koroskin (7/22) Nov 01 2008 I find range_error way too generic. What is range error? Invalid range?
- Andrei Alexandrescu (21/30) Oct 22 2008 I agree. In fact I wanted to ask you all the following question. What do
- Denis Koroskin (24/56) Oct 22 2008 There is sometimes a need to differentiate between a specific exception ...
- Andrei Alexandrescu (4/74) Oct 22 2008 I'd discussed that with Walter. He said that making typedefs
- Max Samukha (16/46) Oct 22 2008 Good idea. What about exceptions thrown from templated code? I suppose
- Andrei Alexandrescu (4/59) Oct 22 2008 That's a good point. By the way, where is Don's code to get the name of
- Denis Koroskin (3/63) Oct 22 2008 http://www.dsource.org/projects/meta/browser/trunk/meta/NameOf.d ?
- Don (3/71) Oct 23 2008 That's not my code, although it's obviously based on my code (not
- Robert Fraser (27/64) Oct 23 2008 Yes, you _could_ use a field... but the "catch a subclass" style is
- Andrei Alexandrescu (8/76) Oct 23 2008 I think you'd be hard-pressed to justify the "if" inside the second
- Sergey Gromov (8/30) Oct 23 2008 If you try every function separately, yes. But I think that the line
- Andrei Alexandrescu (3/33) Oct 23 2008 I agree, but there's no need for a million types to support that.
- Steven Schveighoffer (9/42) Oct 23 2008 I agree that there's both a reason for subclassing and a reason for
- Andrei Alexandrescu (4/6) Oct 23 2008 Yah, that's defined a couple of times in Phobos already, one is
- David Gileadi (22/102) Oct 23 2008 Just an ill-considered idea from someone who has no idea whether it is
- Andrei Alexandrescu (5/115) Oct 23 2008 It's very possible. Parameterizing Exception the same way Tuple is
- Sean Kelly (56/79) Oct 23 2008 It may be different in a user application, but in services it's fairly
- Andrei Alexandrescu (17/103) Oct 23 2008 Thanks for fueling my argument. There's duplication in code examples, as...
- Andrei Alexandrescu (5/116) Oct 23 2008 By the way, this each-exception-has-its-type crap is my #2 pet peeve
- Bill Baxter (15/132) Oct 23 2008 Interesting point. The whole catch(A){} catch(B){} catch(C){} thing
- Andrei Alexandrescu (7/24) Oct 23 2008 The module name can supplant that.
- Steven Schveighoffer (19/121) Oct 23 2008 For the second example, you are assuming that ValidationException is a
- Andrei Alexandrescu (8/128) Oct 23 2008 Sorry, I meant to catch Exception. My point was, if I want to print an
- Steven Schveighoffer (49/177) Oct 23 2008 Sure, but then your example becomes:
- Sergey Gromov (7/10) Oct 23 2008 It's all nice and simple until you want to localize. Then all your
- Bill Baxter (4/14) Oct 23 2008 Just use poedit or whatever to provide localizations of the messages.
- Sergey Gromov (9/24) Oct 23 2008 Where do I get all the messages library may throw? How can I be sure
- Bill Baxter (5/23) Oct 23 2008 Ah, I see your point now. I thought this was still about making
- Andrei Alexandrescu (3/27) Oct 23 2008 I agree. For true localization, string tables are necessary.
- Andrei Alexandrescu (4/15) Oct 23 2008 No, translation would have to be provided via a string table. And guess
- Bill Baxter (13/29) Oct 23 2008 But what Sergey is pointing out is that
- Sergey Gromov (7/38) Oct 23 2008 Correct. Thank you for putting this together. But there is even more t...
- Robert Fraser (3/37) Oct 23 2008 Right -- and what action the program was taking to cause the exception
- Sean Kelly (15/123) Oct 23 2008 Hm... you're right. So here we really have two classes of exceptions,
- Andrei Alexandrescu (8/12) Oct 23 2008 Well put. But I think it's way more effective to start conservatively
- Robert Fraser (6/7) Oct 23 2008 Now that's just wrong. toString should be used for internal debugging
- Robert Fraser (4/84) Oct 23 2008 So in most cases you don't need it... But why throw it out for the cases...
- ore-sama (3/5) Oct 24 2008 Ridiculous. I saw applications running out of memory. This is not someth...
- Bent Rasmussen (5/10) Oct 26 2008 Agreed.
I think the name ArrayBoundsException should be changed to a more general name like BoundsException, OutOfBoundsException or IndexOutOfBoundsException. Then you can use the exception in every class that have some sort of index operation and not just for an array/array class.
Oct 22 2008
On Wed, Oct 22, 2008 at 6:49 AM, Jacob Carlborg <doobnet gmail.com> wrote:I think the name ArrayBoundsException should be changed to a more general name like BoundsException, OutOfBoundsException or IndexOutOfBoundsException. Then you can use the exception in every class that have some sort of index operation and not just for an array/array class.2nded.
Oct 22 2008
On Wed, 22 Oct 2008 16:22:02 +0400, Jarrett Billingsley <jarrett.billingsley gmail.com> wrote:On Wed, Oct 22, 2008 at 6:49 AM, Jacob Carlborg <doobnet gmail.com> wrote:Agreed. BTW, why it is not an Error but Exception?I think the name ArrayBoundsException should be changed to a more general name like BoundsException, OutOfBoundsException or IndexOutOfBoundsException. Then you can use the exception in every class that have some sort of index operation and not just for an array/array class.2nded.
Oct 22 2008
Denis Koroskin wrote:On Wed, 22 Oct 2008 16:22:02 +0400, Jarrett Billingsley <jarrett.billingsley gmail.com> wrote:The Error class was created shortly before release and I didn't get around to reclassifying the exceptions in druntime. From memory though, I think that OutOfMemoryException and UtfException should remain as-is, but the remaining exceptions should probably be errors. Any objections? And as for ArrayBoundsException... how about IndexOutOfBoundsError. It's long, but probably the most self-explanatory. Also, any value in retaining ArrayBoundsError and having it subclass this? I'd think not, but figured I'd ask anyway. SeanOn Wed, Oct 22, 2008 at 6:49 AM, Jacob Carlborg <doobnet gmail.com> wrote:Agreed. BTW, why it is not an Error but Exception?I think the name ArrayBoundsException should be changed to a more general name like BoundsException, OutOfBoundsException or IndexOutOfBoundsException. Then you can use the exception in every class that have some sort of index operation and not just for an array/array class.2nded.
Oct 22 2008
Sean Kelly wrote:Denis Koroskin wrote:Yes it's longer but I gave three suggestions. I just don't want Array in the name so it can be used in general case.On Wed, 22 Oct 2008 16:22:02 +0400, Jarrett Billingsley <jarrett.billingsley gmail.com> wrote:The Error class was created shortly before release and I didn't get around to reclassifying the exceptions in druntime. From memory though, I think that OutOfMemoryException and UtfException should remain as-is, but the remaining exceptions should probably be errors. Any objections? And as for ArrayBoundsException... how about IndexOutOfBoundsError. It's long, but probably the most self-explanatory. Also, any value in retaining ArrayBoundsError and having it subclass this? I'd think not, but figured I'd ask anyway. SeanOn Wed, Oct 22, 2008 at 6:49 AM, Jacob Carlborg <doobnet gmail.com> wrote:Agreed. BTW, why it is not an Error but Exception?I think the name ArrayBoundsException should be changed to a more general name like BoundsException, OutOfBoundsException or IndexOutOfBoundsException. Then you can use the exception in every class that have some sort of index operation and not just for an array/array class.2nded.
Oct 22 2008
Sean Kelly Wrote:Denis Koroskin wrote:What is the criteria for choosing exception verses error? How would this tie into non-recoverable errors discussed with pure function exception handling?On Wed, 22 Oct 2008 16:22:02 +0400, Jarrett Billingsley <jarrett.billingsley gmail.com> wrote:The Error class was created shortly before release and I didn't get around to reclassifying the exceptions in druntime. From memory though, I think that OutOfMemoryException and UtfException should remain as-is, but the remaining exceptions should probably be errors. Any objections?On Wed, Oct 22, 2008 at 6:49 AM, Jacob Carlborg <doobnet gmail.com> wrote:Agreed. BTW, why it is not an Error but Exception?I think the name ArrayBoundsException should be changed to a more general name like BoundsException, OutOfBoundsException or IndexOutOfBoundsException. Then you can use the exception in every class that have some sort of index operation and not just for an array/array class.2nded.And as for ArrayBoundsException... how about IndexOutOfBoundsError. It's long, but probably the most self-explanatory. Also, any value in retaining ArrayBoundsError and having it subclass this? I'd think not, but figured I'd ask anyway. Sean
Oct 22 2008
Jason House wrote:Sean Kelly Wrote:Errors represent situations which are typically non-recoverable--program logic errors, for example, or situations where data corruption may have occurred--while Exceptions represent the bulk of normal execution errors, including OutOfMemory conditions. Regarding pure functions... are you talking about the nothrow guarantee? I haven't given it much thought, but I'd be inclined to say that it's legal for a nothrow function to actually throw a child of Error but not Exception. That ignores OutOfMemoryException though, which is something that the programmer shouldn't have to handle. At the same time, I'd consider an out of memory condition to be quite recoverable, so... SeanDenis Koroskin wrote:What is the criteria for choosing exception verses error? How would this tie into non-recoverable errors discussed with pure function exception handling?On Wed, 22 Oct 2008 16:22:02 +0400, Jarrett Billingsley <jarrett.billingsley gmail.com> wrote:The Error class was created shortly before release and I didn't get around to reclassifying the exceptions in druntime. From memory though, I think that OutOfMemoryException and UtfException should remain as-is, but the remaining exceptions should probably be errors. Any objections?On Wed, Oct 22, 2008 at 6:49 AM, Jacob Carlborg <doobnet gmail.com> wrote:Agreed. BTW, why it is not an Error but Exception?I think the name ArrayBoundsException should be changed to a more general name like BoundsException, OutOfBoundsException or IndexOutOfBoundsException. Then you can use the exception in every class that have some sort of index operation and not just for an array/array class.2nded.
Oct 22 2008
On Wed, Oct 22, 2008 at 7:13 PM, Sean Kelly <sean invisibleduck.org> wrote:Errors represent situations which are typically non-recoverable--program logic errors, for example, or situations where data corruption may have occurred--while Exceptions represent the bulk of normal execution errors, including OutOfMemory conditions.How, pray tell, is an app supposed to recover from an out-of-memory condition?
Oct 22 2008
Jarrett Billingsley wrote:On Wed, Oct 22, 2008 at 7:13 PM, Sean Kelly <sean invisibleduck.org> wrote:By releasing dynamically allocated memory. I'd expect some to be released automatically as the stack is unrolled to the catch point anyway. For example: void main() { try { fn(); } catch( Exception e ) {} int[] x = new int[16384]; } void fn() { int[] x = new int[16384]; fn(); } Eventually this app will run out of memory (hopefully before it runs out of stack space) and an OutOfMemoryException will be thrown. As the stack is unwound, all valid references to this memory will be released. So the allocation in main() should trigger a collection which frees up all the now-unreferenced memory, thus allowing the allocation in main() to succeed. For manual recovery, consider an app that does a great deal of internal caching. On an OutOfMemory condition the app could clear its caches and then retry the operation. This is probably a bad example, but I think the general idea of trapping and recovering from such a state is potentially valid. SeanErrors represent situations which are typically non-recoverable--program logic errors, for example, or situations where data corruption may have occurred--while Exceptions represent the bulk of normal execution errors, including OutOfMemory conditions.How, pray tell, is an app supposed to recover from an out-of-memory condition?
Oct 22 2008
On Wed, Oct 22, 2008 at 8:02 PM, Sean Kelly <sean invisibleduck.org> wrote:For manual recovery, consider an app that does a great deal of internal caching. On an OutOfMemory condition the app could clear its caches and then retry the operation. This is probably a bad example, but I think the general idea of trapping and recovering from such a state is potentially valid.I think that's probably a valid thing to try, and considered it after posting. However, without language support for restarting code at the point of the 'throw' it seems like it wouldn't be all that useful.
Oct 22 2008
On Thu, Oct 23, 2008 at 9:11 AM, Jarrett Billingsley <jarrett.billingsley gmail.com> wrote:On Wed, Oct 22, 2008 at 8:02 PM, Sean Kelly <sean invisibleduck.org> wrote:I think a more common recoverable situation would be an app where user requests opening up a huge image. The app tries to allocate space for the huge image and fails with OutOfMemory. So the app then gives up on creating that huge image and reports to the user "Can't do that. Please buy me some more RAM or turn on some Virtual Memory." But there's still plenty of memory for working on the images that are already loaded. It shouldn't be fatal. --bbFor manual recovery, consider an app that does a great deal of internal caching. On an OutOfMemory condition the app could clear its caches and then retry the operation. This is probably a bad example, but I think the general idea of trapping and recovering from such a state is potentially valid.I think that's probably a valid thing to try, and considered it after posting. However, without language support for restarting code at the point of the 'throw' it seems like it wouldn't be all that useful.
Oct 22 2008
On Wed, 22 Oct 2008 17:02:22 -0700, Sean Kelly wrote:Jarrett Billingsley wrote:I think a good reason for keeping it an exception (ie recoverable) is that out of memory may not be the fault of the program. A completely correct program can be given an out of memory error, especially if another program (like your example) eats it up, would you want your whole system to come to an end?On Wed, Oct 22, 2008 at 7:13 PM, Sean Kelly <sean invisibleduck.org> wrote:By releasing dynamically allocated memory. I'd expect some to be released automatically as the stack is unrolled to the catch point anyway. For example: void main() { try { fn(); } catch( Exception e ) {} int[] x = new int[16384]; } void fn() { int[] x = new int[16384]; fn(); } Eventually this app will run out of memory (hopefully before it runs out of stack space) and an OutOfMemoryException will be thrown. As the stack is unwound, all valid references to this memory will be released. So the allocation in main() should trigger a collection which frees up all the now-unreferenced memory, thus allowing the allocation in main() to succeed. For manual recovery, consider an app that does a great deal of internal caching. On an OutOfMemory condition the app could clear its caches and then retry the operation. This is probably a bad example, but I think the general idea of trapping and recovering from such a state is potentially valid. SeanErrors represent situations which are typically non-recoverable--program logic errors, for example, or situations where data corruption may have occurred--while Exceptions represent the bulk of normal execution errors, including OutOfMemory conditions.How, pray tell, is an app supposed to recover from an out-of-memory condition?
Oct 22 2008
Sean Kelly wrote:Jarrett Billingsley wrote:Didn't see this discussion before I went off my tirade. I agree it's recoverable and in a perfect world this would be so, but look through any large codebase for how many catch(Exception) blocks there are. I'll bet you that NONE of the general catch(Exception) blocks (except the ones that print an error and exit the program) expect to see, or are prepared for, an out of memory exception. Asking programmers to think about out of memory errors is too much. We're trained to assume computers have infinite memory and when they run out, the system/runtime is supposed to do drastic things like crashing our programs - not start introducing strange logic errors all over the place because programmers didn't realize their catch(Exception) blocks had to deal with more than "file doesn't exist"On Wed, Oct 22, 2008 at 7:13 PM, Sean Kelly <sean invisibleduck.org> wrote:By releasing dynamically allocated memory. I'd expect some to be released automatically as the stack is unrolled to the catch point anyway. For example: void main() { try { fn(); } catch( Exception e ) {} int[] x = new int[16384]; } void fn() { int[] x = new int[16384]; fn(); } Eventually this app will run out of memory (hopefully before it runs out of stack space) and an OutOfMemoryException will be thrown. As the stack is unwound, all valid references to this memory will be released. So the allocation in main() should trigger a collection which frees up all the now-unreferenced memory, thus allowing the allocation in main() to succeed. For manual recovery, consider an app that does a great deal of internal caching. On an OutOfMemory condition the app could clear its caches and then retry the operation. This is probably a bad example, but I think the general idea of trapping and recovering from such a state is potentially valid. SeanErrors represent situations which are typically non-recoverable--program logic errors, for example, or situations where data corruption may have occurred--while Exceptions represent the bulk of normal execution errors, including OutOfMemory conditions.How, pray tell, is an app supposed to recover from an out-of-memory condition?
Oct 23 2008
Robert Fraser wrote:Didn't see this discussion before I went off my tirade. I agree it's recoverable and in a perfect world this would be so, but look through any large codebase for how many catch(Exception) blocks there are. I'll bet you that NONE of the general catch(Exception) blocks (except the ones that print an error and exit the program) expect to see, or are prepared for, an out of memory exception.I'd argue that anyone who catches Exception, prints a message, and continues blindly is just asking for trouble. But this seems to have become an ingrained practice anyway, so it's a fair point. However, I'm not sure this is sufficient reason to relabel an out of memory condition as ostensibly unrecoverable.Asking programmers to think about out of memory errors is too much. We're trained to assume computers have infinite memory and when they run out, the system/runtime is supposed to do drastic things like crashing our programs - not start introducing strange logic errors all over the place because programmers didn't realize their catch(Exception) blocks had to deal with more than "file doesn't exist"Perhaps I'm simply getting old... when did memory use become irrelevant? I grant that making an application exception safe is more difficult if out of memory conditions are considered recoverable, but I don't think it's tremendously more difficult. Sean
Oct 23 2008
Sean Kelly wrote:Perhaps I'm simply getting old... when did memory use become irrelevant? I grant that making an application exception safe is more difficult if out of memory conditions are considered recoverable, but I don't think it's tremendously more difficult.I'm currently studying Computer Engineering at university. I don't think a single programming course I've taken has _mentioned_ running out of memory (next quarter I'm taking Operating Systems, so hopefully that will). One class mentioned memory complexity as a side issue, but never got into it. Even at work, I've never been asked to think about it.
Oct 23 2008
On Fri, Oct 24, 2008 at 10:42 AM, Robert Fraser <fraserofthenight gmail.com> wrote:Sean Kelly wrote:People do still develop for embedded devices with small memory and/or no virtual memory. I'm pretty sure it's still a serious concern if you live in that world. --bbPerhaps I'm simply getting old... when did memory use become irrelevant? I grant that making an application exception safe is more difficult if out of memory conditions are considered recoverable, but I don't think it's tremendously more difficult.I'm currently studying Computer Engineering at university. I don't think a single programming course I've taken has _mentioned_ running out of memory (next quarter I'm taking Operating Systems, so hopefully that will). One class mentioned memory complexity as a side issue, but never got into it. Even at work, I've never been asked to think about it.
Oct 23 2008
Bill Baxter wrote:On Fri, Oct 24, 2008 at 10:42 AM, Robert Fraser <fraserofthenight gmail.com> wrote:I'm not saying it doesn't come up in practice; I'm saying developers are trained not to think about it in most cases. And programming to handle a small amount of memory is a different problem than programming to gracefully fail when the program runs out of memory (for example, my program might only use 10k of RAM... but if that 10k isn't there, it might just crash with an error message). The problem with an OutOfMemoryError being treated as an Exception is that if there are many catch(Exception) blocks, an out-of-memory error will propagate logic bugs across the program (since no one is cleaning up the memory, most allocations will fail). So instead of a nice, clean error, the suer will experience weird and frustrating behavior that doesn't mention memory at all.Sean Kelly wrote:People do still develop for embedded devices with small memory and/or no virtual memory. I'm pretty sure it's still a serious concern if you live in that world. --bbPerhaps I'm simply getting old... when did memory use become irrelevant? I grant that making an application exception safe is more difficult if out of memory conditions are considered recoverable, but I don't think it's tremendously more difficult.I'm currently studying Computer Engineering at university. I don't think a single programming course I've taken has _mentioned_ running out of memory (next quarter I'm taking Operating Systems, so hopefully that will). One class mentioned memory complexity as a side issue, but never got into it. Even at work, I've never been asked to think about it.
Oct 24 2008
On Fri, 24 Oct 2008 16:04:53 -0700, Robert Fraser wrote:Bill Baxter wrote:The problem with it being an error is that the programmer has no way to catch and remain usable, leaving the user blissfully unaware he needs to buy more ram. If there are many catch(Exception)'s around, the programmer needs to rethink what he is doing when creating a stable program. D doesn't force a try or throw of exceptions for this very reason; people usually use the catch(Exception) because they don't know what needs to be caught and don't care but are forced to catch it, not because their program is crashing from an exception (well, that is what I do).On Fri, Oct 24, 2008 at 10:42 AM, Robert Fraser <fraserofthenight gmail.com> wrote:I'm not saying it doesn't come up in practice; I'm saying developers are trained not to think about it in most cases. And programming to handle a small amount of memory is a different problem than programming to gracefully fail when the program runs out of memory (for example, my program might only use 10k of RAM... but if that 10k isn't there, it might just crash with an error message). The problem with an OutOfMemoryError being treated as an Exception is that if there are many catch(Exception) blocks, an out-of-memory error will propagate logic bugs across the program (since no one is cleaning up the memory, most allocations will fail). So instead of a nice, clean error, the suer will experience weird and frustrating behavior that doesn't mention memory at all.Sean Kelly wrote:People do still develop for embedded devices with small memory and/or no virtual memory. I'm pretty sure it's still a serious concern if you live in that world. --bbPerhaps I'm simply getting old... when did memory use become irrelevant? I grant that making an application exception safe is more difficult if out of memory conditions are considered recoverable, but I don't think it's tremendously more difficult.I'm currently studying Computer Engineering at university. I don't think a single programming course I've taken has _mentioned_ running out of memory (next quarter I'm taking Operating Systems, so hopefully that will). One class mentioned memory complexity as a side issue, but never got into it. Even at work, I've never been asked to think about it.
Oct 24 2008
Jesse Phillips wrote:On Fri, 24 Oct 2008 16:04:53 -0700, Robert Fraser wrote:Sure there is: catch(OutOfMemoryError) Just like in Java or .Net. The only difference is that it's not caught by a general catch(Exception)Bill Baxter wrote:The problem with it being an error is that the programmer has no way to catch and remain usable,On Fri, Oct 24, 2008 at 10:42 AM, Robert Fraser <fraserofthenight gmail.com> wrote:I'm not saying it doesn't come up in practice; I'm saying developers are trained not to think about it in most cases. And programming to handle a small amount of memory is a different problem than programming to gracefully fail when the program runs out of memory (for example, my program might only use 10k of RAM... but if that 10k isn't there, it might just crash with an error message). The problem with an OutOfMemoryError being treated as an Exception is that if there are many catch(Exception) blocks, an out-of-memory error will propagate logic bugs across the program (since no one is cleaning up the memory, most allocations will fail). So instead of a nice, clean error, the suer will experience weird and frustrating behavior that doesn't mention memory at all.Sean Kelly wrote:People do still develop for embedded devices with small memory and/or no virtual memory. I'm pretty sure it's still a serious concern if you live in that world. --bbPerhaps I'm simply getting old... when did memory use become irrelevant? I grant that making an application exception safe is more difficult if out of memory conditions are considered recoverable, but I don't think it's tremendously more difficult.I'm currently studying Computer Engineering at university. I don't think a single programming course I've taken has _mentioned_ running out of memory (next quarter I'm taking Operating Systems, so hopefully that will). One class mentioned memory complexity as a side issue, but never got into it. Even at work, I've never been asked to think about it.leaving the user blissfully unaware he needs to buy more ram. If there are many catch(Exception)'s around, the programmer needs to rethink what he is doing when creating a stable program.Probably. But when you have a team of 300 programmers, this is a bit harder to do, and catch(Exception) _is_ a powerful tool for generalized recoverable error handling.D doesn't force a try or throw of exceptions for this very reason; people usually use the catch(Exception) because they don't know what needs to be caught and don't care but are forced to catch it, not because their program is crashing from an exception (well, that is what I do).People also use it to say to the user "this didn't work; try something else"? In 99% of cases, this is fine, but when memory is involved, the programmer has a whole lot more to think about and would often want to catch the memory exception at a higher level.
Oct 25 2008
On Sat, 25 Oct 2008 15:45:51 -0700, Robert Fraser wrote:Jesse Phillips wrote:Oops, from past discussions about the difference I somehow got the idea that an Error couldn't be caught. While out of memory still falls under recoverable, I can see why putting greater importance over other exceptions would be good.On Fri, 24 Oct 2008 16:04:53 -0700, Robert Fraser wrote:Sure there is: catch(OutOfMemoryError) Just like in Java or .Net. The only difference is that it's not caught by a general catch(Exception)Bill Baxter wrote:The problem with it being an error is that the programmer has no way to catch and remain usable,On Fri, Oct 24, 2008 at 10:42 AM, Robert Fraser <fraserofthenight gmail.com> wrote:I'm not saying it doesn't come up in practice; I'm saying developers are trained not to think about it in most cases. And programming to handle a small amount of memory is a different problem than programming to gracefully fail when the program runs out of memory (for example, my program might only use 10k of RAM... but if that 10k isn't there, it might just crash with an error message). The problem with an OutOfMemoryError being treated as an Exception is that if there are many catch(Exception) blocks, an out-of-memory error will propagate logic bugs across the program (since no one is cleaning up the memory, most allocations will fail). So instead of a nice, clean error, the suer will experience weird and frustrating behavior that doesn't mention memory at all.Sean Kelly wrote:People do still develop for embedded devices with small memory and/or no virtual memory. I'm pretty sure it's still a serious concern if you live in that world. --bbPerhaps I'm simply getting old... when did memory use become irrelevant? I grant that making an application exception safe is more difficult if out of memory conditions are considered recoverable, but I don't think it's tremendously more difficult.I'm currently studying Computer Engineering at university. I don't think a single programming course I've taken has _mentioned_ running out of memory (next quarter I'm taking Operating Systems, so hopefully that will). One class mentioned memory complexity as a side issue, but never got into it. Even at work, I've never been asked to think about it.leaving the user blissfully unaware he needs to buy more ram. If there are many catch(Exception)'s around, the programmer needs to rethink what he is doing when creating a stable program.Probably. But when you have a team of 300 programmers, this is a bit harder to do, and catch(Exception) _is_ a powerful tool for generalized recoverable error handling.D doesn't force a try or throw of exceptions for this very reason; people usually use the catch(Exception) because they don't know what needs to be caught and don't care but are forced to catch it, not because their program is crashing from an exception (well, that is what I do).People also use it to say to the user "this didn't work; try something else"? In 99% of cases, this is fine, but when memory is involved, the programmer has a whole lot more to think about and would often want to catch the memory exception at a higher level.
Oct 25 2008
Jesse Phillips wrote:On Sat, 25 Oct 2008 15:45:51 -0700, Robert Fraser wrote:After some thought, I'm inclined to agree. While an OOM condition might be recoverable without any explicit effort, I think it's a good idea to encourage that it receive special handling by classifying it as an Error. Since D is a systems language I don't consider any error condition to be necessarily unrecoverable anyway, so reclassifying OutOfMemory doesn't imply anything to me other than that it should be handled explicitly rather than accidentally by trapping and tossing out out as an Exception. SeanJesse Phillips wrote:Oops, from past discussions about the difference I somehow got the idea that an Error couldn't be caught. While out of memory still falls under recoverable, I can see why putting greater importance over other exceptions would be good.D doesn't force a try or throw of exceptions for this very reason; people usually use the catch(Exception) because they don't know what needs to be caught and don't care but are forced to catch it, not because their program is crashing from an exception (well, that is what I do).People also use it to say to the user "this didn't work; try something else"? In 99% of cases, this is fine, but when memory is involved, the programmer has a whole lot more to think about and would often want to catch the memory exception at a higher level.
Oct 31 2008
On Thu, 23 Oct 2008 04:02:22 +0400, Sean Kelly <sean invisibleduck.org> wrote:Jarrett Billingsley wrote:I think that OutOfMemoryException should *not* be recoverable. Instead, language should provide some hookable callback (like onOutOfMemoryError()) which is called when memory limit is reached so that program may free some unused memory (which is held by user since it is not garbage-collected) and tries to allocate the memory again without failure (return true from callback). User might decide to re-throw some other kind of *exception*, like NotEnoughMemoryException(), to catch and recover, or pass it (return false from callback) which in turn will finally throw OutOfMemoryError().On Wed, Oct 22, 2008 at 7:13 PM, Sean Kelly <sean invisibleduck.org> wrote:By releasing dynamically allocated memory. I'd expect some to be released automatically as the stack is unrolled to the catch point anyway. For example: void main() { try { fn(); } catch( Exception e ) {} int[] x = new int[16384]; } void fn() { int[] x = new int[16384]; fn(); } Eventually this app will run out of memory (hopefully before it runs out of stack space) and an OutOfMemoryException will be thrown. As the stack is unwound, all valid references to this memory will be released. So the allocation in main() should trigger a collection which frees up all the now-unreferenced memory, thus allowing the allocation in main() to succeed. For manual recovery, consider an app that does a great deal of internal caching. On an OutOfMemory condition the app could clear its caches and then retry the operation. This is probably a bad example, but I think the general idea of trapping and recovering from such a state is potentially valid. SeanErrors represent situations which are typically non-recoverable--program logic errors, for example, or situations where data corruption may have occurred--while Exceptions represent the bulk of normal execution errors, including OutOfMemory conditions.How, pray tell, is an app supposed to recover from an out-of-memory condition?
Oct 23 2008
Denis Koroskin wrote:On Thu, 23 Oct 2008 04:02:22 +0400, Sean Kelly <sean invisibleduck.org> wrote:But one of the best things possible to do is unwind the stack and fall back to a higher position with less state. A function cannot do that, an exception can. Why do you guys want to avoid exceptions in one of the few cases when they are exactly, but exactly what the doctor prescribed? AndreiJarrett Billingsley wrote:I think that OutOfMemoryException should *not* be recoverable. Instead, language should provide some hookable callback (like onOutOfMemoryError()) which is called when memory limit is reached so that program may free some unused memory (which is held by user since it is not garbage-collected) and tries to allocate the memory again without failure (return true from callback). User might decide to re-throw some other kind of *exception*, like NotEnoughMemoryException(), to catch and recover, or pass it (return false from callback) which in turn will finally throw OutOfMemoryError().On Wed, Oct 22, 2008 at 7:13 PM, Sean Kelly <sean invisibleduck.org> wrote:By releasing dynamically allocated memory. I'd expect some to be released automatically as the stack is unrolled to the catch point anyway. For example: void main() { try { fn(); } catch( Exception e ) {} int[] x = new int[16384]; } void fn() { int[] x = new int[16384]; fn(); } Eventually this app will run out of memory (hopefully before it runs out of stack space) and an OutOfMemoryException will be thrown. As the stack is unwound, all valid references to this memory will be released. So the allocation in main() should trigger a collection which frees up all the now-unreferenced memory, thus allowing the allocation in main() to succeed. For manual recovery, consider an app that does a great deal of internal caching. On an OutOfMemory condition the app could clear its caches and then retry the operation. This is probably a bad example, but I think the general idea of trapping and recovering from such a state is potentially valid. SeanErrors represent situations which are typically non-recoverable--program logic errors, for example, or situations where data corruption may have occurred--while Exceptions represent the bulk of normal execution errors, including OutOfMemory conditions.How, pray tell, is an app supposed to recover from an out-of-memory condition?
Oct 23 2008
On Thu, 23 Oct 2008 17:47:52 +0400, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:Denis Koroskin wrote:You can do that, of course, just don't handle the onOutOfMemory custom callback (per my proposal).On Thu, 23 Oct 2008 04:02:22 +0400, Sean Kelly <sean invisibleduck.org> wrote:But one of the best things possible to do is unwind the stack and fall back to a higher position with less state. A function cannot do that, an exception can.Jarrett Billingsley wrote:I think that OutOfMemoryException should *not* be recoverable. Instead, language should provide some hookable callback (like onOutOfMemoryError()) which is called when memory limit is reached so that program may free some unused memory (which is held by user since it is not garbage-collected) and tries to allocate the memory again without failure (return true from callback). User might decide to re-throw some other kind of *exception*, like NotEnoughMemoryException(), to catch and recover, or pass it (return false from callback) which in turn will finally throw OutOfMemoryError().On Wed, Oct 22, 2008 at 7:13 PM, Sean Kelly <sean invisibleduck.org> wrote:By releasing dynamically allocated memory. I'd expect some to be released automatically as the stack is unrolled to the catch point anyway. For example: void main() { try { fn(); } catch( Exception e ) {} int[] x = new int[16384]; } void fn() { int[] x = new int[16384]; fn(); } Eventually this app will run out of memory (hopefully before it runs out of stack space) and an OutOfMemoryException will be thrown. As the stack is unwound, all valid references to this memory will be released. So the allocation in main() should trigger a collection which frees up all the now-unreferenced memory, thus allowing the allocation in main() to succeed. For manual recovery, consider an app that does a great deal of internal caching. On an OutOfMemory condition the app could clear its caches and then retry the operation. This is probably a bad example, but I think the general idea of trapping and recovering from such a state is potentially valid. SeanErrors represent situations which are typically non-recoverable--program logic errors, for example, or situations where data corruption may have occurred--while Exceptions represent the bulk of normal execution errors, including OutOfMemory conditions.How, pray tell, is an app supposed to recover from an out-of-memory condition?Why do you guys want to avoid exceptions in one of the few cases when they are exactly, but exactly what the doctor prescribed? AndreiMy concern is to avoid program flow interrupt and fall-back to some recovery code if possible. One of such cases is OutOfMemoryException. For example, I recieve some network message. An object is constructed and about to be inserted into the message list. Imagine that an OutOfMemoryException is thrown during the insertion. It is quite hard (if possible) and not generally disirable to revert network state: I have to emulate that message is not recieved yet so that I get it later (at a second attempt, after OutOfMemory exception is processed and some memory freed), etc. Besides, where would you put the catch(OutOfMemoryError) code? Far from the exception source point, most likely, which is even worse for recovery. The solution I would prefer is to avoid that situation at all! No memory? Fine, I'll clean this memory pool and that one, too. Try again, please! Still no memory? Then re-throw the exception so that upper forces handle the situation. I don't say that exception recovery is not needed - of course it is! - but I prefer to avoid it if possible. It is just safer. Leave the user unaware that an out of memory error has been occured and recovered from is my best wish.
Oct 23 2008
Denis Koroskin wrote:On Thu, 23 Oct 2008 17:47:52 +0400, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:I understand your motivation. But you can easily implement all of that within client code without changing anything anywhere. Notice that the problem is more general, e.g. if creating a socket fail you might ask the user to plug a cable or start a wireless card etc. Just catch the exception at the appropriate level, take the appropriate measure, and goto RETRY. :o) AndreiDenis Koroskin wrote:You can do that, of course, just don't handle the onOutOfMemory custom callback (per my proposal).On Thu, 23 Oct 2008 04:02:22 +0400, Sean Kelly <sean invisibleduck.org> wrote:But one of the best things possible to do is unwind the stack and fall back to a higher position with less state. A function cannot do that, an exception can.Jarrett Billingsley wrote:I think that OutOfMemoryException should *not* be recoverable. Instead, language should provide some hookable callback (like onOutOfMemoryError()) which is called when memory limit is reached so that program may free some unused memory (which is held by user since it is not garbage-collected) and tries to allocate the memory again without failure (return true from callback). User might decide to re-throw some other kind of *exception*, like NotEnoughMemoryException(), to catch and recover, or pass it (return false from callback) which in turn will finally throw OutOfMemoryError().On Wed, Oct 22, 2008 at 7:13 PM, Sean Kelly <sean invisibleduck.org> wrote:By releasing dynamically allocated memory. I'd expect some to be released automatically as the stack is unrolled to the catch point anyway. For example: void main() { try { fn(); } catch( Exception e ) {} int[] x = new int[16384]; } void fn() { int[] x = new int[16384]; fn(); } Eventually this app will run out of memory (hopefully before it runs out of stack space) and an OutOfMemoryException will be thrown. As the stack is unwound, all valid references to this memory will be released. So the allocation in main() should trigger a collection which frees up all the now-unreferenced memory, thus allowing the allocation in main() to succeed. For manual recovery, consider an app that does a great deal of internal caching. On an OutOfMemory condition the app could clear its caches and then retry the operation. This is probably a bad example, but I think the general idea of trapping and recovering from such a state is potentially valid. SeanErrors represent situations which are typically non-recoverable--program logic errors, for example, or situations where data corruption may have occurred--while Exceptions represent the bulk of normal execution errors, including OutOfMemory conditions.How, pray tell, is an app supposed to recover from an out-of-memory condition?Why do you guys want to avoid exceptions in one of the few cases when they are exactly, but exactly what the doctor prescribed? AndreiMy concern is to avoid program flow interrupt and fall-back to some recovery code if possible. One of such cases is OutOfMemoryException. For example, I recieve some network message. An object is constructed and about to be inserted into the message list. Imagine that an OutOfMemoryException is thrown during the insertion. It is quite hard (if possible) and not generally disirable to revert network state: I have to emulate that message is not recieved yet so that I get it later (at a second attempt, after OutOfMemory exception is processed and some memory freed), etc. Besides, where would you put the catch(OutOfMemoryError) code? Far from the exception source point, most likely, which is even worse for recovery. The solution I would prefer is to avoid that situation at all! No memory? Fine, I'll clean this memory pool and that one, too. Try again, please! Still no memory? Then re-throw the exception so that upper forces handle the situation. I don't say that exception recovery is not needed - of course it is! - but I prefer to avoid it if possible. It is just safer. Leave the user unaware that an out of memory error has been occured and recovered from is my best wish.
Oct 23 2008
Denis Koroskin wrote:I think that OutOfMemoryException should *not* be recoverable. Instead, language should provide some hookable callback (like onOutOfMemoryError()) which is called when memory limit is reached so that program may free some unused memory (which is held by user since it is not garbage-collected) and tries to allocate the memory again without failure (return true from callback). User might decide to re-throw some other kind of *exception*, like NotEnoughMemoryException(), to catch and recover, or pass it (return false from callback) which in turn will finally throw OutOfMemoryError().This is a fair point, but how does one implement this safely? Let's say for the sake of argument that onOutOfMemoryError() can be hooked by the user and may try to recover. Now: auto x = new int[BIG_NUMBER]; Let's say that gc_malloc() is implemented like so: void* gc_malloc( size_t sz ) { void* ptr; do { ptr = doMalloc(sz); if( ptr is null ) onOutOfMemoryError(); } while( ptr is null ); return ptr; } Now let's assume that the first attempted allocation fails and onOutOfMemoryError() frees some memory rather than throwing so the allocation is attempted again. But BIG_NUMBER is so darn big that the allocation fails again. And once again onOutOfMemoryError() tries to free some memory and returns instead of throwing. Is there any way to structure the recovery mechanism to avoid this situation given that onOutOfMemoryError() has no idea that it's being called in such a loop? gc_malloc() could certainly give up and throw after a certain number of failed attempts, but putting the onus on the caller of onOutOfMemoryError() to deal with this situation is not reasonable in my opinion. Sean
Oct 23 2008
Sean Kelly wrote:Denis Koroskin wrote:Perfectly put. Again: why prevent use of exceptions for the one case that they fit the best? AndreiI think that OutOfMemoryException should *not* be recoverable. Instead, language should provide some hookable callback (like onOutOfMemoryError()) which is called when memory limit is reached so that program may free some unused memory (which is held by user since it is not garbage-collected) and tries to allocate the memory again without failure (return true from callback). User might decide to re-throw some other kind of *exception*, like NotEnoughMemoryException(), to catch and recover, or pass it (return false from callback) which in turn will finally throw OutOfMemoryError().This is a fair point, but how does one implement this safely? Let's say for the sake of argument that onOutOfMemoryError() can be hooked by the user and may try to recover. Now: auto x = new int[BIG_NUMBER]; Let's say that gc_malloc() is implemented like so: void* gc_malloc( size_t sz ) { void* ptr; do { ptr = doMalloc(sz); if( ptr is null ) onOutOfMemoryError(); } while( ptr is null ); return ptr; } Now let's assume that the first attempted allocation fails and onOutOfMemoryError() frees some memory rather than throwing so the allocation is attempted again. But BIG_NUMBER is so darn big that the allocation fails again. And once again onOutOfMemoryError() tries to free some memory and returns instead of throwing. Is there any way to structure the recovery mechanism to avoid this situation given that onOutOfMemoryError() has no idea that it's being called in such a loop? gc_malloc() could certainly give up and throw after a certain number of failed attempts, but putting the onus on the caller of onOutOfMemoryError() to deal with this situation is not reasonable in my opinion.
Oct 23 2008
Wed, 22 Oct 2008 19:18:57 -0400, Jarrett Billingsley wrote:On Wed, Oct 22, 2008 at 7:13 PM, Sean Kelly <sean invisibleduck.org> wrote:In an image editor, a user asks to create a huge image (50k x 50k). You try, run out of memory, and gracefully tell the user that the image was too big and you didn't succeed.Errors represent situations which are typically non-recoverable--program logic errors, for example, or situations where data corruption may have occurred--while Exceptions represent the bulk of normal execution errors, including OutOfMemory conditions.How, pray tell, is an app supposed to recover from an out-of-memory condition?
Oct 23 2008
Sergey Gromov wrote:Wed, 22 Oct 2008 19:18:57 -0400, Jarrett Billingsley wrote:I could extract many instances of this pattern from my programs. Unfortunately, current bugs in the compiler, phobos, or both lead to sudden death of the application under certain circumstances. I hope one day I'll get around to investigating that. AndreiOn Wed, Oct 22, 2008 at 7:13 PM, Sean Kelly <sean invisibleduck.org> wrote:In an image editor, a user asks to create a huge image (50k x 50k). You try, run out of memory, and gracefully tell the user that the image was too big and you didn't succeed.Errors represent situations which are typically non-recoverable--program logic errors, for example, or situations where data corruption may have occurred--while Exceptions represent the bulk of normal execution errors, including OutOfMemory conditions.How, pray tell, is an app supposed to recover from an out-of-memory condition?
Oct 23 2008
Thu, 23 Oct 2008 08:45:45 -0500, Andrei Alexandrescu wrote:Sergey Gromov wrote:I've noticed that failed new sometimes simply returned null instead of throwing an exception. I remember it happened in a 3-line piece of test code.Wed, 22 Oct 2008 19:18:57 -0400, Jarrett Billingsley wrote:I could extract many instances of this pattern from my programs. Unfortunately, current bugs in the compiler, phobos, or both lead to sudden death of the application under certain circumstances. I hope one day I'll get around to investigating that.On Wed, Oct 22, 2008 at 7:13 PM, Sean Kelly <sean invisibleduck.org> wrote:In an image editor, a user asks to create a huge image (50k x 50k). You try, run out of memory, and gracefully tell the user that the image was too big and you didn't succeed.Errors represent situations which are typically non-recoverable--program logic errors, for example, or situations where data corruption may have occurred--while Exceptions represent the bulk of normal execution errors, including OutOfMemory conditions.How, pray tell, is an app supposed to recover from an out-of-memory condition?
Oct 23 2008
Sergey Gromov wrote:I've noticed that failed new sometimes simply returned null instead of throwing an exception. I remember it happened in a 3-line piece of test code.I think I've corrected all these in druntime. if I haven't please let me know. Sean
Oct 23 2008
Thu, 23 Oct 2008 08:30:31 -0700, Sean Kelly wrote:Sergey Gromov wrote:I wasn't using druntime nor Tango when I stumbled upon that. I'm glad to hear that those issues were addressed.I've noticed that failed new sometimes simply returned null instead of throwing an exception. I remember it happened in a 3-line piece of test code.I think I've corrected all these in druntime. if I haven't please let me know.
Oct 23 2008
Sean Kelly wrote:Denis Koroskin wrote:Ah NOOOOO! Please don't make an out of memory catchable with a plain catch(Exception) .... In most programs... pretty much every non-trivial desktop application I can think of... an out-of memory state is basically unrecoverable. In the few cases it would need to be, there would need to be significant handling code, and that would have to be at the right location in the program (i.e. when first opening a file), not in the closest catch-all block some intern down the hallway may have thrown in. there. catch(Exception) shouldn't be used - but it is, quite often, so things that would cause issues that a user could not normally be expected to recover from should be Error subclasses. Indexing I could see being an exception since that's deterministic and the user's fault. So I guess I disagree on both counts ;-P. Although since index errors don't appear in release modes in D, that gives more case for it to be an Error.On Wed, 22 Oct 2008 16:22:02 +0400, Jarrett Billingsley <jarrett.billingsley gmail.com> wrote:The Error class was created shortly before release and I didn't get around to reclassifying the exceptions in druntime. From memory though, I think that OutOfMemoryException and UtfException should remain as-is, but the remaining exceptions should probably be errors. Any objections? And as for ArrayBoundsException... how about IndexOutOfBoundsError. It's long, but probably the most self-explanatory. Also, any value in retaining ArrayBoundsError and having it subclass this? I'd think not, but figured I'd ask anyway. SeanOn Wed, Oct 22, 2008 at 6:49 AM, Jacob Carlborg <doobnet gmail.com> wrote:Agreed. BTW, why it is not an Error but Exception?I think the name ArrayBoundsException should be changed to a more general name like BoundsException, OutOfBoundsException or IndexOutOfBoundsException. Then you can use the exception in every class that have some sort of index operation and not just for an array/array class.2nded.
Oct 23 2008
Robert Fraser wrote:Sean Kelly wrote:Make OutOfMemoryException the own subclass of Throwable? Then we have Throwable Exception Error OutOfMemoryException or we maybe we can have (jokingly) Throwable Exception // Recoverable Error // Should not be recoverable ChallengingException // Recoverable but I won't touch it. OutOfMemoryException // Let programmer to force GC to release memory CPUOnFireException // Let programmer to call local fire station through modem. // etc...Denis Koroskin wrote:Ah NOOOOO! Please don't make an out of memory catchable with a plain catch(Exception) .... In most programs... pretty much every non-trivial desktop application I can think of... an out-of memory state is basically unrecoverable. In the few cases it would need to be, there would need to be significant handling code, and that would have to be at the right location in the program (i.e. when first opening a file), not in the closest catch-all block some intern down the hallway may have thrown in. there. catch(Exception) shouldn't be used - but it is, quite often, so things that would cause issues that a user could not normally be expected to recover from should be Error subclasses. Indexing I could see being an exception since that's deterministic and the user's fault. So I guess I disagree on both counts ;-P. Although since index errors don't appear in release modes in D, that gives more case for it to be an Error.On Wed, 22 Oct 2008 16:22:02 +0400, Jarrett Billingsley <jarrett.billingsley gmail.com> wrote:The Error class was created shortly before release and I didn't get around to reclassifying the exceptions in druntime. From memory though, I think that OutOfMemoryException and UtfException should remain as-is, but the remaining exceptions should probably be errors. Any objections? And as for ArrayBoundsException... how about IndexOutOfBoundsError. It's long, but probably the most self-explanatory. Also, any value in retaining ArrayBoundsError and having it subclass this? I'd think not, but figured I'd ask anyway. SeanOn Wed, Oct 22, 2008 at 6:49 AM, Jacob Carlborg <doobnet gmail.com> wrote:Agreed. BTW, why it is not an Error but Exception?I think the name ArrayBoundsException should be changed to a more general name like BoundsException, OutOfBoundsException or IndexOutOfBoundsException. Then you can use the exception in every class that have some sort of index operation and not just for an array/array class.2nded.
Oct 23 2008
KennyTM~ wrote:Robert Fraser wrote:Even though the last suggestion was partially meant as a joke, I think it is actually a good idea. One could have a third hierarchy of exception classes, for exceptions like OutOfMemoryException that one should be able to catch, but that shouldn't be caught by default along with other exceptions. Sort of a "middle ground" between Exception and Error. Not sure about the name "ChallengingException", though. ;) How about SpecialException, CriticalException or something like that? -LarsSean Kelly wrote:Make OutOfMemoryException the own subclass of Throwable? Then we have Throwable Exception Error OutOfMemoryException or we maybe we can have (jokingly) Throwable Exception // Recoverable Error // Should not be recoverable ChallengingException // Recoverable but I won't touch it. OutOfMemoryException // Let programmer to force GC to release memory CPUOnFireException // Let programmer to call local fire station through modem. // etc...Denis Koroskin wrote:Ah NOOOOO! Please don't make an out of memory catchable with a plain catch(Exception) .... In most programs... pretty much every non-trivial desktop application I can think of... an out-of memory state is basically unrecoverable. In the few cases it would need to be, there would need to be significant handling code, and that would have to be at the right location in the program (i.e. when first opening a file), not in the closest catch-all block some intern down the hallway may have thrown in. precedent there. catch(Exception) shouldn't be used - but it is, quite often, so things that would cause issues that a user could not normally be expected to recover from should be Error subclasses. Indexing I could see being an exception since that's deterministic and the user's fault. So I guess I disagree on both counts ;-P. Although since index errors don't appear in release modes in D, that gives more case for it to be an Error.On Wed, 22 Oct 2008 16:22:02 +0400, Jarrett Billingsley <jarrett.billingsley gmail.com> wrote:The Error class was created shortly before release and I didn't get around to reclassifying the exceptions in druntime. From memory though, I think that OutOfMemoryException and UtfException should remain as-is, but the remaining exceptions should probably be errors. Any objections? And as for ArrayBoundsException... how about IndexOutOfBoundsError. It's long, but probably the most self-explanatory. Also, any value in retaining ArrayBoundsError and having it subclass this? I'd think not, but figured I'd ask anyway. SeanOn Wed, Oct 22, 2008 at 6:49 AM, Jacob Carlborg <doobnet gmail.com> wrote:Agreed. BTW, why it is not an Error but Exception?I think the name ArrayBoundsException should be changed to a more general name like BoundsException, OutOfBoundsException or IndexOutOfBoundsException. Then you can use the exception in every class that have some sort of index operation and not just for an array/array class.2nded.
Oct 25 2008
Wed, 22 Oct 2008 12:01:36 -0700, Sean Kelly wrote:And as for ArrayBoundsException... how about IndexOutOfBoundsError. It's long, but probably the most self-explanatory. Also, any value in retaining ArrayBoundsError and having it subclass this? I'd think not, but figured I'd ask anyway.Maybe IndexingError ? There are not necessarily any bounds when you're indexing into an arbitrary collection.
Oct 23 2008
Sergey Gromov wrote:Wed, 22 Oct 2008 12:01:36 -0700, Sean Kelly wrote:STL has range_error. I like that because it's rather general. AndreiAnd as for ArrayBoundsException... how about IndexOutOfBoundsError. It's long, but probably the most self-explanatory. Also, any value in retaining ArrayBoundsError and having it subclass this? I'd think not, but figured I'd ask anyway.Maybe IndexingError ? There are not necessarily any bounds when you're indexing into an arbitrary collection.
Oct 23 2008
Andrei Alexandrescu wrote:Sergey Gromov wrote:The terminology matches D's new range concept anyway, which is a nice perk. Works for me. SeanWed, 22 Oct 2008 12:01:36 -0700, Sean Kelly wrote:STL has range_error. I like that because it's rather general.And as for ArrayBoundsException... how about IndexOutOfBoundsError. It's long, but probably the most self-explanatory. Also, any value in retaining ArrayBoundsError and having it subclass this? I'd think not, but figured I'd ask anyway.Maybe IndexingError ? There are not necessarily any bounds when you're indexing into an arbitrary collection.
Oct 31 2008
On Sat, 01 Nov 2008 01:56:49 +0300, Sean Kelly <sean invisibleduck.org> wrote:Andrei Alexandrescu wrote:I find range_error way too generic. What is range error? Invalid range? OutOfRangeError is more suitable imo. Range!(int) r = ...; // random-access range int t = r[2]; // okay, within range int s = r[100]; // error, our of rangeSergey Gromov wrote:The terminology matches D's new range concept anyway, which is a nice perk. Works for me. SeanWed, 22 Oct 2008 12:01:36 -0700, Sean Kelly wrote:STL has range_error. I like that because it's rather general.And as for ArrayBoundsException... how about IndexOutOfBoundsError. It's long, but probably the most self-explanatory. Also, any value in retaining ArrayBoundsError and having it subclass this? I'd think not, but figured I'd ask anyway.Maybe IndexingError ? There are not necessarily any bounds when you're indexing into an arbitrary collection.
Nov 01 2008
Jarrett Billingsley wrote:On Wed, Oct 22, 2008 at 6:49 AM, Jacob Carlborg <doobnet gmail.com> wrote:I agree. In fact I wanted to ask you all the following question. What do you think about the current exception hierarchy in phobos? I think it is terrible. Each module in std you open, the first piece of code to be seen is the "class ThisModuleNameException" definition. In many (most?) cases the module-specific exception does absolutely nothing in addition to its base class. The putative reader (including me) tends to scroll non-critically over that passage without even blinking, mumbling in a trance - of course, yes, each module should define at least one exception type. Until one day when you stop scrolling and say, wait a minute. This all is repetition. And there are alternatives to catching by type - you can catch the base type and consult a field. And in fact I don't remember seeing code that depends on exceptions thrown from different modules having different types. There's something wrong here! I think most exception classes in phobos should be yanked if it's possible for their functionality (often nil) to be moved in the Exception base class. The module name should be a member. If someone needs to deal with an exception thrown from a specific module, they can always inspect the field. We don't need a huge hierarchy for that. AndreiI think the name ArrayBoundsException should be changed to a more general name like BoundsException, OutOfBoundsException or IndexOutOfBoundsException. Then you can use the exception in every class that have some sort of index operation and not just for an array/array class.2nded.
Oct 22 2008
On Wed, 22 Oct 2008 19:06:24 +0400, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:Jarrett Billingsley wrote:There is sometimes a need to differentiate between a specific exception and a generic one, even though the former or does nothing. typedef Exception MyException; // might be a good compromise try { throw new MyException("reason"); } catch (MyException e) { // catch concrete exception } catch (Exception e) { // catch generic exception } This code currently doesn't work, because compiler thinks that MyException and Exception are of the same type, which is wrong - MyException is kind of a subclass of Exception, as the following sample shows: typedef Exception MyException; void main() { MyException me = new MyException("reason"); Exception e = me; // implicit downcast me = e; // doesn't work, it is an upcast Object o = me; // ICE! :) } Could anyone put it into bugzilla? (I have no access to HTTP currently :()On Wed, Oct 22, 2008 at 6:49 AM, Jacob Carlborg <doobnet gmail.com> wrote:I agree. In fact I wanted to ask you all the following question. What do you think about the current exception hierarchy in phobos? I think it is terrible. Each module in std you open, the first piece of code to be seen is the "class ThisModuleNameException" definition. In many (most?) cases the module-specific exception does absolutely nothing in addition to its base class. The putative reader (including me) tends to scroll non-critically over that passage without even blinking, mumbling in a trance - of course, yes, each module should define at least one exception type. Until one day when you stop scrolling and say, wait a minute. This all is repetition. And there are alternatives to catching by type - you can catch the base type and consult a field. And in fact I don't remember seeing code that depends on exceptions thrown from different modules having different types. There's something wrong here! I think most exception classes in phobos should be yanked if it's possible for their functionality (often nil) to be moved in the Exception base class. The module name should be a member. If someone needs to deal with an exception thrown from a specific module, they can always inspect the field. We don't need a huge hierarchy for that. AndreiI think the name ArrayBoundsException should be changed to a more general name like BoundsException, OutOfBoundsException or IndexOutOfBoundsException. Then you can use the exception in every class that have some sort of index operation and not just for an array/array class.2nded.
Oct 22 2008
Denis Koroskin wrote:On Wed, 22 Oct 2008 19:06:24 +0400, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:I'd discussed that with Walter. He said that making typedefs full-fledged classes would be technically difficult. AndreiJarrett Billingsley wrote:There is sometimes a need to differentiate between a specific exception and a generic one, even though the former or does nothing. typedef Exception MyException; // might be a good compromise try { throw new MyException("reason"); } catch (MyException e) { // catch concrete exception } catch (Exception e) { // catch generic exception } This code currently doesn't work, because compiler thinks that MyException and Exception are of the same type, which is wrong - MyException is kind of a subclass of Exception, as the following sample shows: typedef Exception MyException; void main() { MyException me = new MyException("reason"); Exception e = me; // implicit downcast me = e; // doesn't work, it is an upcast Object o = me; // ICE! :) } Could anyone put it into bugzilla? (I have no access to HTTP currently :()On Wed, Oct 22, 2008 at 6:49 AM, Jacob Carlborg <doobnet gmail.com> wrote:I agree. In fact I wanted to ask you all the following question. What do you think about the current exception hierarchy in phobos? I think it is terrible. Each module in std you open, the first piece of code to be seen is the "class ThisModuleNameException" definition. In many (most?) cases the module-specific exception does absolutely nothing in addition to its base class. The putative reader (including me) tends to scroll non-critically over that passage without even blinking, mumbling in a trance - of course, yes, each module should define at least one exception type. Until one day when you stop scrolling and say, wait a minute. This all is repetition. And there are alternatives to catching by type - you can catch the base type and consult a field. And in fact I don't remember seeing code that depends on exceptions thrown from different modules having different types. There's something wrong here! I think most exception classes in phobos should be yanked if it's possible for their functionality (often nil) to be moved in the Exception base class. The module name should be a member. If someone needs to deal with an exception thrown from a specific module, they can always inspect the field. We don't need a huge hierarchy for that. AndreiI think the name ArrayBoundsException should be changed to a more general name like BoundsException, OutOfBoundsException or IndexOutOfBoundsException. Then you can use the exception in every class that have some sort of index operation and not just for an array/array class.2nded.
Oct 22 2008
On Wed, 22 Oct 2008 10:06:24 -0500, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:Jarrett Billingsley wrote:Good idea. What about exceptions thrown from templated code? I suppose mixins and ordinary template instances should be treated differently: modue a; template Foo() { void Foo() { throw new Exception; } } ---- module b; alias Foo!() foo; // Exception's module should probably be 'a' mixin Foo; // Exception's module is 'b'?On Wed, Oct 22, 2008 at 6:49 AM, Jacob Carlborg <doobnet gmail.com> wrote:I agree. In fact I wanted to ask you all the following question. What do you think about the current exception hierarchy in phobos? I think it is terrible. Each module in std you open, the first piece of code to be seen is the "class ThisModuleNameException" definition. In many (most?) cases the module-specific exception does absolutely nothing in addition to its base class. The putative reader (including me) tends to scroll non-critically over that passage without even blinking, mumbling in a trance - of course, yes, each module should define at least one exception type. Until one day when you stop scrolling and say, wait a minute. This all is repetition. And there are alternatives to catching by type - you can catch the base type and consult a field. And in fact I don't remember seeing code that depends on exceptions thrown from different modules having different types. There's something wrong here! I think most exception classes in phobos should be yanked if it's possible for their functionality (often nil) to be moved in the Exception base class. The module name should be a member. If someone needs to deal with an exception thrown from a specific module, they can always inspect the field. We don't need a huge hierarchy for that. AndreiI think the name ArrayBoundsException should be changed to a more general name like BoundsException, OutOfBoundsException or IndexOutOfBoundsException. Then you can use the exception in every class that have some sort of index operation and not just for an array/array class.2nded.
Oct 22 2008
Max Samukha wrote:On Wed, 22 Oct 2008 10:06:24 -0500, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:That's a good point. By the way, where is Don's code to get the name of the current module? AndreiJarrett Billingsley wrote:Good idea. What about exceptions thrown from templated code? I suppose mixins and ordinary template instances should be treated differently: modue a; template Foo() { void Foo() { throw new Exception; } } ---- module b; alias Foo!() foo; // Exception's module should probably be 'a' mixin Foo; // Exception's module is 'b'?On Wed, Oct 22, 2008 at 6:49 AM, Jacob Carlborg <doobnet gmail.com> wrote:I agree. In fact I wanted to ask you all the following question. What do you think about the current exception hierarchy in phobos? I think it is terrible. Each module in std you open, the first piece of code to be seen is the "class ThisModuleNameException" definition. In many (most?) cases the module-specific exception does absolutely nothing in addition to its base class. The putative reader (including me) tends to scroll non-critically over that passage without even blinking, mumbling in a trance - of course, yes, each module should define at least one exception type. Until one day when you stop scrolling and say, wait a minute. This all is repetition. And there are alternatives to catching by type - you can catch the base type and consult a field. And in fact I don't remember seeing code that depends on exceptions thrown from different modules having different types. There's something wrong here! I think most exception classes in phobos should be yanked if it's possible for their functionality (often nil) to be moved in the Exception base class. The module name should be a member. If someone needs to deal with an exception thrown from a specific module, they can always inspect the field. We don't need a huge hierarchy for that. AndreiI think the name ArrayBoundsException should be changed to a more general name like BoundsException, OutOfBoundsException or IndexOutOfBoundsException. Then you can use the exception in every class that have some sort of index operation and not just for an array/array class.2nded.
Oct 22 2008
On Wed, 22 Oct 2008 20:25:15 +0400, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:Max Samukha wrote:http://www.dsource.org/projects/meta/browser/trunk/meta/NameOf.d ?On Wed, 22 Oct 2008 10:06:24 -0500, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:That's a good point. By the way, where is Don's code to get the name of the current module? AndreiJarrett Billingsley wrote:Good idea. What about exceptions thrown from templated code? I suppose mixins and ordinary template instances should be treated differently: modue a; template Foo() { void Foo() { throw new Exception; } } ---- module b; alias Foo!() foo; // Exception's module should probably be 'a' mixin Foo; // Exception's module is 'b'?On Wed, Oct 22, 2008 at 6:49 AM, Jacob Carlborg <doobnet gmail.com> wrote:I agree. In fact I wanted to ask you all the following question. What do you think about the current exception hierarchy in phobos? I think it is terrible. Each module in std you open, the first piece of code to be seen is the "class ThisModuleNameException" definition. In many (most?) cases the module-specific exception does absolutely nothing in addition to its base class. The putative reader (including me) tends to scroll non-critically over that passage without even blinking, mumbling in a trance - of course, yes, each module should define at least one exception type. Until one day when you stop scrolling and say, wait a minute. This all is repetition. And there are alternatives to catching by type - you can catch the base type and consult a field. And in fact I don't remember seeing code that depends on exceptions thrown from different modules having different types. There's something wrong here! I think most exception classes in phobos should be yanked if it's possible for their functionality (often nil) to be moved in the Exception base class. The module name should be a member. If someone needs to deal with an exception thrown from a specific module, they can always inspect the field. We don't need a huge hierarchy for that. AndreiI think the name ArrayBoundsException should be changed to a more general name like BoundsException, OutOfBoundsException or IndexOutOfBoundsException. Then you can use the exception in every class that have some sort of index operation and not just for an array/array class.2nded.
Oct 22 2008
Denis Koroskin wrote:On Wed, 22 Oct 2008 20:25:15 +0400, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:That's not my code, although it's obviously based on my code (not acknowledged!)Max Samukha wrote:http://www.dsource.org/projects/meta/browser/trunk/meta/NameOf.d ?On Wed, 22 Oct 2008 10:06:24 -0500, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:That's a good point. By the way, where is Don's code to get the name of the current module? AndreiJarrett Billingsley wrote:Good idea. What about exceptions thrown from templated code? I suppose mixins and ordinary template instances should be treated differently: modue a; template Foo() { void Foo() { throw new Exception; } } ---- module b; alias Foo!() foo; // Exception's module should probably be 'a' mixin Foo; // Exception's module is 'b'?On Wed, Oct 22, 2008 at 6:49 AM, Jacob Carlborg <doobnet gmail.com> wrote:I agree. In fact I wanted to ask you all the following question. What do you think about the current exception hierarchy in phobos? I think it is terrible. Each module in std you open, the first piece of code to be seen is the "class ThisModuleNameException" definition. In many (most?) cases the module-specific exception does absolutely nothing in addition to its base class. The putative reader (including me) tends to scroll non-critically over that passage without even blinking, mumbling in a trance - of course, yes, each module should define at least one exception type. Until one day when you stop scrolling and say, wait a minute. This all is repetition. And there are alternatives to catching by type - you can catch the base type and consult a field. And in fact I don't remember seeing code that depends on exceptions thrown from different modules having different types. There's something wrong here! I think most exception classes in phobos should be yanked if it's possible for their functionality (often nil) to be moved in the Exception base class. The module name should be a member. If someone needs to deal with an exception thrown from a specific module, they can always inspect the field. We don't need a huge hierarchy for that. AndreiI think the name ArrayBoundsException should be changed to a more general name like BoundsException, OutOfBoundsException or IndexOutOfBoundsException. Then you can use the exception in every class that have some sort of index operation and not just for an array/array class.2nded.
Oct 23 2008
Andrei Alexandrescu wrote:Jarrett Billingsley wrote:Yes, you _could_ use a field... but the "catch a subclass" style is already there and is supported by the language, so _why_ use a field? Which of the following is easier?: Option A: --------- try { new Socket(30587); } catch(SocketException e) { printf("Could not open socket\n"); } Option B: --------- try { new Socket(30587); } catch(Exception e) { if(e.type == ExceptionType.Socket) printf("Could not open socket\n"); else throw e; }On Wed, Oct 22, 2008 at 6:49 AM, Jacob Carlborg <doobnet gmail.com> wrote:I agree. In fact I wanted to ask you all the following question. What do you think about the current exception hierarchy in phobos? I think it is terrible. Each module in std you open, the first piece of code to be seen is the "class ThisModuleNameException" definition. In many (most?) cases the module-specific exception does absolutely nothing in addition to its base class. The putative reader (including me) tends to scroll non-critically over that passage without even blinking, mumbling in a trance - of course, yes, each module should define at least one exception type. Until one day when you stop scrolling and say, wait a minute. This all is repetition. And there are alternatives to catching by type - you can catch the base type and consult a field. And in fact I don't remember seeing code that depends on exceptions thrown from different modules having different types. There's something wrong here! I think most exception classes in phobos should be yanked if it's possible for their functionality (often nil) to be moved in the Exception base class. The module name should be a member. If someone needs to deal with an exception thrown from a specific module, they can always inspect the field. We don't need a huge hierarchy for that. AndreiI think the name ArrayBoundsException should be changed to a more general name like BoundsException, OutOfBoundsException or IndexOutOfBoundsException. Then you can use the exception in every class that have some sort of index operation and not just for an array/array class.2nded.
Oct 23 2008
Robert Fraser wrote:Andrei Alexandrescu wrote:I think you'd be hard-pressed to justify the "if" inside the second example. You couldn't create a Socket, period. It doesn't matter where exactly the exception was generated from. That's one thing about large exception hierarchies: everybody can come with cute examples on how they could be useful. As soon as the rubber hits the road, however, differentiating exceptions by type becomes useless. AndreiJarrett Billingsley wrote:Yes, you _could_ use a field... but the "catch a subclass" style is already there and is supported by the language, so _why_ use a field? Which of the following is easier?: Option A: --------- try { new Socket(30587); } catch(SocketException e) { printf("Could not open socket\n"); } Option B: --------- try { new Socket(30587); } catch(Exception e) { if(e.type == ExceptionType.Socket) printf("Could not open socket\n"); else throw e; }On Wed, Oct 22, 2008 at 6:49 AM, Jacob Carlborg <doobnet gmail.com> wrote:I agree. In fact I wanted to ask you all the following question. What do you think about the current exception hierarchy in phobos? I think it is terrible. Each module in std you open, the first piece of code to be seen is the "class ThisModuleNameException" definition. In many (most?) cases the module-specific exception does absolutely nothing in addition to its base class. The putative reader (including me) tends to scroll non-critically over that passage without even blinking, mumbling in a trance - of course, yes, each module should define at least one exception type. Until one day when you stop scrolling and say, wait a minute. This all is repetition. And there are alternatives to catching by type - you can catch the base type and consult a field. And in fact I don't remember seeing code that depends on exceptions thrown from different modules having different types. There's something wrong here! I think most exception classes in phobos should be yanked if it's possible for their functionality (often nil) to be moved in the Exception base class. The module name should be a member. If someone needs to deal with an exception thrown from a specific module, they can always inspect the field. We don't need a huge hierarchy for that. AndreiI think the name ArrayBoundsException should be changed to a more general name like BoundsException, OutOfBoundsException or IndexOutOfBoundsException. Then you can use the exception in every class that have some sort of index operation and not just for an array/array class.2nded.
Oct 23 2008
Thu, 23 Oct 2008 08:43:04 -0500, Andrei Alexandrescu wrote:Robert Fraser wrote:If you try every function separately, yes. But I think that the line between recoverable and non-recoverable exceptions is arbitrary and depends on the situation. It makes sense to try/catch a transaction, not separate calls. I can retry connection transaction if the socket open fails, but the whole upper-level transaction should fail if there is a database inconsistency or out of memory.Option B: --------- try { new Socket(30587); } catch(Exception e) { if(e.type == ExceptionType.Socket) printf("Could not open socket\n"); else throw e; }I think you'd be hard-pressed to justify the "if" inside the second example. You couldn't create a Socket, period. It doesn't matter where exactly the exception was generated from. That's one thing about large exception hierarchies: everybody can come with cute examples on how they could be useful. As soon as the rubber hits the road, however, differentiating exceptions by type becomes useless.
Oct 23 2008
Sergey Gromov wrote:Thu, 23 Oct 2008 08:43:04 -0500, Andrei Alexandrescu wrote:I agree, but there's no need for a million types to support that. AndreiRobert Fraser wrote:If you try every function separately, yes. But I think that the line between recoverable and non-recoverable exceptions is arbitrary and depends on the situation. It makes sense to try/catch a transaction, not separate calls. I can retry connection transaction if the socket open fails, but the whole upper-level transaction should fail if there is a database inconsistency or out of memory.Option B: --------- try { new Socket(30587); } catch(Exception e) { if(e.type == ExceptionType.Socket) printf("Could not open socket\n"); else throw e; }I think you'd be hard-pressed to justify the "if" inside the second example. You couldn't create a Socket, period. It doesn't matter where exactly the exception was generated from. That's one thing about large exception hierarchies: everybody can come with cute examples on how they could be useful. As soon as the rubber hits the road, however, differentiating exceptions by type becomes useless.
Oct 23 2008
"Andrei Alexandrescu" wroteSergey Gromov wrote:I agree that there's both a reason for subclassing and a reason for parameterizing. I don't want only one Exception class in the whole hierarchy that is parameterized as given in the example, but I also hate it when the reason for the exception is only implemented by the type of the exception. A good example is many OS errors, those should be parameterized on the errno (and should provide an easy way to build the string from strerror). -SteveThu, 23 Oct 2008 08:43:04 -0500, Andrei Alexandrescu wrote:I agree, but there's no need for a million types to support that.Robert Fraser wrote:If you try every function separately, yes. But I think that the line between recoverable and non-recoverable exceptions is arbitrary and depends on the situation. It makes sense to try/catch a transaction, not separate calls. I can retry connection transaction if the socket open fails, but the whole upper-level transaction should fail if there is a database inconsistency or out of memory.Option B: --------- try { new Socket(30587); } catch(Exception e) { if(e.type == ExceptionType.Socket) printf("Could not open socket\n"); else throw e; }I think you'd be hard-pressed to justify the "if" inside the second example. You couldn't create a Socket, period. It doesn't matter where exactly the exception was generated from. That's one thing about large exception hierarchies: everybody can come with cute examples on how they could be useful. As soon as the rubber hits the road, however, differentiating exceptions by type becomes useless.
Oct 23 2008
Steven Schveighoffer wrote:A good example is many OS errors, those should be parameterized on the errno (and should provide an easy way to build the string from strerror).Yah, that's defined a couple of times in Phobos already, one is StdioException and the other I forgot... so silly. Andrei
Oct 23 2008
Andrei Alexandrescu wrote:Robert Fraser wrote:Just an ill-considered idea from someone who has no idea whether it is even technically possible: try { new Socket(30587); } catch(Exception!(SocketConnect) e) { printf("Could not open socket\n"); } catch(Exception ex) { printf("Serious trouble--I probably shouldn't have caught this at all!\n"); } Granted, you'd still need to define SocketConnect and its ilk, but since they'd be simple (and in some cases empty) data containers they would be quick and easy to define, especially since you wouldn't need to implement all of Exception's constructors. Of course, this is back to catching by type again, so maybe it's not a good idea even if it is possible.Andrei Alexandrescu wrote:I think you'd be hard-pressed to justify the "if" inside the second example. You couldn't create a Socket, period. It doesn't matter where exactly the exception was generated from. That's one thing about large exception hierarchies: everybody can come with cute examples on how they could be useful. As soon as the rubber hits the road, however, differentiating exceptions by type becomes useless. AndreiJarrett Billingsley wrote:Yes, you _could_ use a field... but the "catch a subclass" style is already there and is supported by the language, so _why_ use a field? Which of the following is easier?: Option A: --------- try { new Socket(30587); } catch(SocketException e) { printf("Could not open socket\n"); } Option B: --------- try { new Socket(30587); } catch(Exception e) { if(e.type == ExceptionType.Socket) printf("Could not open socket\n"); else throw e; }On Wed, Oct 22, 2008 at 6:49 AM, Jacob Carlborg <doobnet gmail.com> wrote:I agree. In fact I wanted to ask you all the following question. What do you think about the current exception hierarchy in phobos? I think it is terrible. Each module in std you open, the first piece of code to be seen is the "class ThisModuleNameException" definition. In many (most?) cases the module-specific exception does absolutely nothing in addition to its base class. The putative reader (including me) tends to scroll non-critically over that passage without even blinking, mumbling in a trance - of course, yes, each module should define at least one exception type. Until one day when you stop scrolling and say, wait a minute. This all is repetition. And there are alternatives to catching by type - you can catch the base type and consult a field. And in fact I don't remember seeing code that depends on exceptions thrown from different modules having different types. There's something wrong here! I think most exception classes in phobos should be yanked if it's possible for their functionality (often nil) to be moved in the Exception base class. The module name should be a member. If someone needs to deal with an exception thrown from a specific module, they can always inspect the field. We don't need a huge hierarchy for that. AndreiI think the name ArrayBoundsException should be changed to a more general name like BoundsException, OutOfBoundsException or IndexOutOfBoundsException. Then you can use the exception in every class that have some sort of index operation and not just for an array/array class.2nded.
Oct 23 2008
David Gileadi wrote:Andrei Alexandrescu wrote:It's very possible. Parameterizing Exception the same way Tuple is parameterized (with e.g. module name and name/value type pairs) is a great idea! AndreiRobert Fraser wrote:Just an ill-considered idea from someone who has no idea whether it is even technically possible: try { new Socket(30587); } catch(Exception!(SocketConnect) e) { printf("Could not open socket\n"); } catch(Exception ex) { printf("Serious trouble--I probably shouldn't have caught this at all!\n"); } Granted, you'd still need to define SocketConnect and its ilk, but since they'd be simple (and in some cases empty) data containers they would be quick and easy to define, especially since you wouldn't need to implement all of Exception's constructors. Of course, this is back to catching by type again, so maybe it's not a good idea even if it is possible.Andrei Alexandrescu wrote:I think you'd be hard-pressed to justify the "if" inside the second example. You couldn't create a Socket, period. It doesn't matter where exactly the exception was generated from. That's one thing about large exception hierarchies: everybody can come with cute examples on how they could be useful. As soon as the rubber hits the road, however, differentiating exceptions by type becomes useless. AndreiJarrett Billingsley wrote:Yes, you _could_ use a field... but the "catch a subclass" style is already there and is supported by the language, so _why_ use a field? Which of the following is easier?: Option A: --------- try { new Socket(30587); } catch(SocketException e) { printf("Could not open socket\n"); } Option B: --------- try { new Socket(30587); } catch(Exception e) { if(e.type == ExceptionType.Socket) printf("Could not open socket\n"); else throw e; }On Wed, Oct 22, 2008 at 6:49 AM, Jacob Carlborg <doobnet gmail.com> wrote:I agree. In fact I wanted to ask you all the following question. What do you think about the current exception hierarchy in phobos? I think it is terrible. Each module in std you open, the first piece of code to be seen is the "class ThisModuleNameException" definition. In many (most?) cases the module-specific exception does absolutely nothing in addition to its base class. The putative reader (including me) tends to scroll non-critically over that passage without even blinking, mumbling in a trance - of course, yes, each module should define at least one exception type. Until one day when you stop scrolling and say, wait a minute. This all is repetition. And there are alternatives to catching by type - you can catch the base type and consult a field. And in fact I don't remember seeing code that depends on exceptions thrown from different modules having different types. There's something wrong here! I think most exception classes in phobos should be yanked if it's possible for their functionality (often nil) to be moved in the Exception base class. The module name should be a member. If someone needs to deal with an exception thrown from a specific module, they can always inspect the field. We don't need a huge hierarchy for that. AndreiI think the name ArrayBoundsException should be changed to a more general name like BoundsException, OutOfBoundsException or IndexOutOfBoundsException. Then you can use the exception in every class that have some sort of index operation and not just for an array/array class.2nded.
Oct 23 2008
Andrei Alexandrescu wrote:Robert Fraser wrote:It may be different in a user application, but in services it's fairly common to have specialized code for handling different exception types. And more importantly, it's common to want different exception types to propagate to different levels for handling. Sure, one could use a generic exception handler at each level that rethrows if the detected type isn't one that handler cares about but why do this when filtering on type is a language feature? For example, let's say I have a network service that's backed by a SQL database. My main program loop may look something like this: bool connected = false; while( true ) { try { while( true ) { auto r = acceptRequest(); scope(failure) r.tellFailed(); if( !connected ) connectToDB(); handleRequest( r ); } } catch( SqlException e ) { connected = false; log( e ); } catch( Exception e ) { log( e ); } } ... void handleRequest( Request r ) { scope(failure) r.tellFailed( "General error" ); try { // process r } catch( AuthException e ) { r.tellFailed( "Authentication failure" ); } catch( ValidationException e ) { r.tellFailed( "Invalid request format" ); } } Being able to trap specific types of exceptions makes this code cleaner and more succinct than it would be otherwise. If this weren't possible I'd have to trap, check, and rethrow certain exceptions at different levels to ensure that the proper handler saw them. SeanOption B: --------- try { new Socket(30587); } catch(Exception e) { if(e.type == ExceptionType.Socket) printf("Could not open socket\n"); else throw e; }I think you'd be hard-pressed to justify the "if" inside the second example. You couldn't create a Socket, period. It doesn't matter where exactly the exception was generated from. That's one thing about large exception hierarchies: everybody can come with cute examples on how they could be useful. As soon as the rubber hits the road, however, differentiating exceptions by type becomes useless.
Oct 23 2008
Sean Kelly wrote:Andrei Alexandrescu wrote:Thanks for fueling my argument. There's duplication in code examples, as in many other examples I've seen in favor of by-type handling. First example: catch( Exception e ) { if (e.origin = "sql") connected = false; log( e ); } Less code and no duplication. Second example is even starker: catch( AuthException e ) { r.tellFailed( e.toString ); } Clearly the need is to factor in the message to print in the exception, at least in this case and many like it. AndreiRobert Fraser wrote:It may be different in a user application, but in services it's fairly common to have specialized code for handling different exception types. And more importantly, it's common to want different exception types to propagate to different levels for handling. Sure, one could use a generic exception handler at each level that rethrows if the detected type isn't one that handler cares about but why do this when filtering on type is a language feature? For example, let's say I have a network service that's backed by a SQL database. My main program loop may look something like this: bool connected = false; while( true ) { try { while( true ) { auto r = acceptRequest(); scope(failure) r.tellFailed(); if( !connected ) connectToDB(); handleRequest( r ); } } catch( SqlException e ) { connected = false; log( e ); } catch( Exception e ) { log( e ); } } ... void handleRequest( Request r ) { scope(failure) r.tellFailed( "General error" ); try { // process r } catch( AuthException e ) { r.tellFailed( "Authentication failure" ); } catch( ValidationException e ) { r.tellFailed( "Invalid request format" ); } } Being able to trap specific types of exceptions makes this code cleaner and more succinct than it would be otherwise. If this weren't possible I'd have to trap, check, and rethrow certain exceptions at different levels to ensure that the proper handler saw them.Option B: --------- try { new Socket(30587); } catch(Exception e) { if(e.type == ExceptionType.Socket) printf("Could not open socket\n"); else throw e; }I think you'd be hard-pressed to justify the "if" inside the second example. You couldn't create a Socket, period. It doesn't matter where exactly the exception was generated from. That's one thing about large exception hierarchies: everybody can come with cute examples on how they could be useful. As soon as the rubber hits the road, however, differentiating exceptions by type becomes useless.
Oct 23 2008
Andrei Alexandrescu wrote:Sean Kelly wrote:after "Follow carefully my pocket watch... OO is good for everything... OO is good for everything... to use, inherit... to use, inherit..." AndreiAndrei Alexandrescu wrote:Thanks for fueling my argument. There's duplication in code examples, as in many other examples I've seen in favor of by-type handling. First example: catch( Exception e ) { if (e.origin = "sql") connected = false; log( e ); } Less code and no duplication. Second example is even starker: catch( AuthException e ) { r.tellFailed( e.toString ); } Clearly the need is to factor in the message to print in the exception, at least in this case and many like it. AndreiRobert Fraser wrote:It may be different in a user application, but in services it's fairly common to have specialized code for handling different exception types. And more importantly, it's common to want different exception types to propagate to different levels for handling. Sure, one could use a generic exception handler at each level that rethrows if the detected type isn't one that handler cares about but why do this when filtering on type is a language feature? For example, let's say I have a network service that's backed by a SQL database. My main program loop may look something like this: bool connected = false; while( true ) { try { while( true ) { auto r = acceptRequest(); scope(failure) r.tellFailed(); if( !connected ) connectToDB(); handleRequest( r ); } } catch( SqlException e ) { connected = false; log( e ); } catch( Exception e ) { log( e ); } } ... void handleRequest( Request r ) { scope(failure) r.tellFailed( "General error" ); try { // process r } catch( AuthException e ) { r.tellFailed( "Authentication failure" ); } catch( ValidationException e ) { r.tellFailed( "Invalid request format" ); } } Being able to trap specific types of exceptions makes this code cleaner and more succinct than it would be otherwise. If this weren't possible I'd have to trap, check, and rethrow certain exceptions at different levels to ensure that the proper handler saw them.Option B: --------- try { new Socket(30587); } catch(Exception e) { if(e.type == ExceptionType.Socket) printf("Could not open socket\n"); else throw e; }I think you'd be hard-pressed to justify the "if" inside the second example. You couldn't create a Socket, period. It doesn't matter where exactly the exception was generated from. That's one thing about large exception hierarchies: everybody can come with cute examples on how they could be useful. As soon as the rubber hits the road, however, differentiating exceptions by type becomes useless.
Oct 23 2008
On Fri, Oct 24, 2008 at 4:08 AM, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:Andrei Alexandrescu wrote:Interesting point. The whole catch(A){} catch(B){} catch(C){} thing is basically if-then-else on very similar types, which is exactly what the OO crowd says you should try to avoid in any other situation. You should be using polymorphism! But ok, types are good for one thing, and that's ensuring global uniqueness. That seems to be the real point of the billion exception types, to give them unique identifiers that the compiler can check. You can give your exceptions a typecode or a string identifier, like your origin=="sql", but then the compiler won't tell you if your type is unique. And it won't tell you there's a problem if you mistakenly type origin=="SQL" instead of "sql". I think it boils down to a kind of static typing vs dynamic typing argument. --bbSean Kelly wrote:"Follow carefully my pocket watch... OO is good for everything... OO is good for everything... to use, inherit... to use, inherit..."Andrei Alexandrescu wrote:Thanks for fueling my argument. There's duplication in code examples, as in many other examples I've seen in favor of by-type handling. First example: catch( Exception e ) { if (e.origin = "sql") connected = false; log( e ); } Less code and no duplication. Second example is even starker: catch( AuthException e ) { r.tellFailed( e.toString ); } Clearly the need is to factor in the message to print in the exception, at least in this case and many like it. AndreiRobert Fraser wrote:It may be different in a user application, but in services it's fairly common to have specialized code for handling different exception types. And more importantly, it's common to want different exception types to propagate to different levels for handling. Sure, one could use a generic exception handler at each level that rethrows if the detected type isn't one that handler cares about but why do this when filtering on type is a language feature? For example, let's say I have a network service that's backed by a SQL database. My main program loop may look something like this: bool connected = false; while( true ) { try { while( true ) { auto r = acceptRequest(); scope(failure) r.tellFailed(); if( !connected ) connectToDB(); handleRequest( r ); } } catch( SqlException e ) { connected = false; log( e ); } catch( Exception e ) { log( e ); } } ... void handleRequest( Request r ) { scope(failure) r.tellFailed( "General error" ); try { // process r } catch( AuthException e ) { r.tellFailed( "Authentication failure" ); } catch( ValidationException e ) { r.tellFailed( "Invalid request format" ); } } Being able to trap specific types of exceptions makes this code cleaner and more succinct than it would be otherwise. If this weren't possible I'd have to trap, check, and rethrow certain exceptions at different levels to ensure that the proper handler saw them.Option B: --------- try { new Socket(30587); } catch(Exception e) { if(e.type == ExceptionType.Socket) printf("Could not open socket\n"); else throw e; }I think you'd be hard-pressed to justify the "if" inside the second example. You couldn't create a Socket, period. It doesn't matter where exactly the exception was generated from. That's one thing about large exception hierarchies: everybody can come with cute examples on how they could be useful. As soon as the rubber hits the road, however, differentiating exceptions by type becomes useless.
Oct 23 2008
Bill Baxter wrote:On Fri, Oct 24, 2008 at 4:08 AM, Andrei AlexandrescuYes!"Follow carefully my pocket watch... OO is good for everything... OO is good for everything... to use, inherit... to use, inherit..."Interesting point. The whole catch(A){} catch(B){} catch(C){} thing is basically if-then-else on very similar types, which is exactly what the OO crowd says you should try to avoid in any other situation. You should be using polymorphism!But ok, types are good for one thing, and that's ensuring global uniqueness. That seems to be the real point of the billion exception types, to give them unique identifiers that the compiler can check. You can give your exceptions a typecode or a string identifier, like your origin=="sql", but then the compiler won't tell you if your type is unique. And it won't tell you there's a problem if you mistakenly type origin=="SQL" instead of "sql".The module name can supplant that.I think it boils down to a kind of static typing vs dynamic typing argument.To some extent, yes. But, I think an adept of static typing should also recognize when it brings nothing to the table, and IMHO exceptions are one of those cases. Andrei
Oct 23 2008
"Andrei Alexandrescu" wroteSean Kelly wrote:For the second example, you are assuming that ValidationException is a subclass of AuthException. I think in this case, ValidationException and AuthException might share a common parent (SqlException) which you do NOT want to catch. It is advantageous in this case to have both a hierarchy through inheritance and a hierarchy through parameters. Here's another idea, to avoid rethrows, what about some pre-handler code that tests if an exception is what you want? Perhaps the same mechanism that is used by template constraints: catch(SqlException e) if (e.reason is Auth || e.reason is Validation) { r.tellFailed(e.toString()); } That gives you the same mechanism used with typing and without the rethrows, without creating N subclasses of SqlException, and without multiple repetitive blocks that do the same thing. It looks more readable to me too. Not sure how exception code works, so I don't know how plausible this is. -SteveAndrei Alexandrescu wrote:Thanks for fueling my argument. There's duplication in code examples, as in many other examples I've seen in favor of by-type handling. First example: catch( Exception e ) { if (e.origin = "sql") connected = false; log( e ); } Less code and no duplication. Second example is even starker: catch( AuthException e ) { r.tellFailed( e.toString ); } Clearly the need is to factor in the message to print in the exception, at least in this case and many like it.Robert Fraser wrote:It may be different in a user application, but in services it's fairly common to have specialized code for handling different exception types. And more importantly, it's common to want different exception types to propagate to different levels for handling. Sure, one could use a generic exception handler at each level that rethrows if the detected type isn't one that handler cares about but why do this when filtering on type is a language feature? For example, let's say I have a network service that's backed by a SQL database. My main program loop may look something like this: bool connected = false; while( true ) { try { while( true ) { auto r = acceptRequest(); scope(failure) r.tellFailed(); if( !connected ) connectToDB(); handleRequest( r ); } } catch( SqlException e ) { connected = false; log( e ); } catch( Exception e ) { log( e ); } } ... void handleRequest( Request r ) { scope(failure) r.tellFailed( "General error" ); try { // process r } catch( AuthException e ) { r.tellFailed( "Authentication failure" ); } catch( ValidationException e ) { r.tellFailed( "Invalid request format" ); } } Being able to trap specific types of exceptions makes this code cleaner and more succinct than it would be otherwise. If this weren't possible I'd have to trap, check, and rethrow certain exceptions at different levels to ensure that the proper handler saw them.Option B: --------- try { new Socket(30587); } catch(Exception e) { if(e.type == ExceptionType.Socket) printf("Could not open socket\n"); else throw e; }I think you'd be hard-pressed to justify the "if" inside the second example. You couldn't create a Socket, period. It doesn't matter where exactly the exception was generated from. That's one thing about large exception hierarchies: everybody can come with cute examples on how they could be useful. As soon as the rubber hits the road, however, differentiating exceptions by type becomes useless.
Oct 23 2008
Steven Schveighoffer wrote:"Andrei Alexandrescu" wroteSorry, I meant to catch Exception. My point was, if I want to print an informative message, the exception should be able to provide it without having to encode it in its type.Sean Kelly wrote:For the second example, you are assuming that ValidationException is a subclass of AuthException.Andrei Alexandrescu wrote:Thanks for fueling my argument. There's duplication in code examples, as in many other examples I've seen in favor of by-type handling. First example: catch( Exception e ) { if (e.origin = "sql") connected = false; log( e ); } Less code and no duplication. Second example is even starker: catch( AuthException e ) { r.tellFailed( e.toString ); } Clearly the need is to factor in the message to print in the exception, at least in this case and many like it.Robert Fraser wrote:It may be different in a user application, but in services it's fairly common to have specialized code for handling different exception types. And more importantly, it's common to want different exception types to propagate to different levels for handling. Sure, one could use a generic exception handler at each level that rethrows if the detected type isn't one that handler cares about but why do this when filtering on type is a language feature? For example, let's say I have a network service that's backed by a SQL database. My main program loop may look something like this: bool connected = false; while( true ) { try { while( true ) { auto r = acceptRequest(); scope(failure) r.tellFailed(); if( !connected ) connectToDB(); handleRequest( r ); } } catch( SqlException e ) { connected = false; log( e ); } catch( Exception e ) { log( e ); } } ... void handleRequest( Request r ) { scope(failure) r.tellFailed( "General error" ); try { // process r } catch( AuthException e ) { r.tellFailed( "Authentication failure" ); } catch( ValidationException e ) { r.tellFailed( "Invalid request format" ); } } Being able to trap specific types of exceptions makes this code cleaner and more succinct than it would be otherwise. If this weren't possible I'd have to trap, check, and rethrow certain exceptions at different levels to ensure that the proper handler saw them.Option B: --------- try { new Socket(30587); } catch(Exception e) { if(e.type == ExceptionType.Socket) printf("Could not open socket\n"); else throw e; }I think you'd be hard-pressed to justify the "if" inside the second example. You couldn't create a Socket, period. It doesn't matter where exactly the exception was generated from. That's one thing about large exception hierarchies: everybody can come with cute examples on how they could be useful. As soon as the rubber hits the road, however, differentiating exceptions by type becomes useless.I think in this case, ValidationException and AuthException might share a common parent (SqlException) which you do NOT want to catch. It is advantageous in this case to have both a hierarchy through inheritance and a hierarchy through parameters. Here's another idea, to avoid rethrows, what about some pre-handler code that tests if an exception is what you want? Perhaps the same mechanism that is used by template constraints: catch(SqlException e) if (e.reason is Auth || e.reason is Validation) { r.tellFailed(e.toString()); }I think we're a bit too immersed in the "what can we add to the language". In this case, for example, I see no reason for the "if" to be moved inside and call it a day. Andrei
Oct 23 2008
"Andrei Alexandrescu" wroteSteven Schveighoffer wrote:Sure, but then your example becomes: catch(Exception e) { if(e.reason is Auth || e.reason is Validation) r.tellFailed(e.toString()); else throw e; } Not that it looks terrible, but I just want it to be clear that your one-liner isn't sufficient."Andrei Alexandrescu" wroteSorry, I meant to catch Exception. My point was, if I want to print an informative message, the exception should be able to provide it without having to encode it in its type.Sean Kelly wrote:For the second example, you are assuming that ValidationException is a subclass of AuthException.Andrei Alexandrescu wrote:Thanks for fueling my argument. There's duplication in code examples, as in many other examples I've seen in favor of by-type handling. First example: catch( Exception e ) { if (e.origin = "sql") connected = false; log( e ); } Less code and no duplication. Second example is even starker: catch( AuthException e ) { r.tellFailed( e.toString ); } Clearly the need is to factor in the message to print in the exception, at least in this case and many like it.Robert Fraser wrote:It may be different in a user application, but in services it's fairly common to have specialized code for handling different exception types. And more importantly, it's common to want different exception types to propagate to different levels for handling. Sure, one could use a generic exception handler at each level that rethrows if the detected type isn't one that handler cares about but why do this when filtering on type is a language feature? For example, let's say I have a network service that's backed by a SQL database. My main program loop may look something like this: bool connected = false; while( true ) { try { while( true ) { auto r = acceptRequest(); scope(failure) r.tellFailed(); if( !connected ) connectToDB(); handleRequest( r ); } } catch( SqlException e ) { connected = false; log( e ); } catch( Exception e ) { log( e ); } } ... void handleRequest( Request r ) { scope(failure) r.tellFailed( "General error" ); try { // process r } catch( AuthException e ) { r.tellFailed( "Authentication failure" ); } catch( ValidationException e ) { r.tellFailed( "Invalid request format" ); } } Being able to trap specific types of exceptions makes this code cleaner and more succinct than it would be otherwise. If this weren't possible I'd have to trap, check, and rethrow certain exceptions at different levels to ensure that the proper handler saw them.Option B: --------- try { new Socket(30587); } catch(Exception e) { if(e.type == ExceptionType.Socket) printf("Could not open socket\n"); else throw e; }I think you'd be hard-pressed to justify the "if" inside the second example. You couldn't create a Socket, period. It doesn't matter where exactly the exception was generated from. That's one thing about large exception hierarchies: everybody can come with cute examples on how they could be useful. As soon as the rubber hits the road, however, differentiating exceptions by type becomes useless.A fair point. It might help in situations like this (with your philosophy of not subclassing for specific reasons): try { try { ... } catch(SqlException sql) { if(sql.reason == Auth || sql.reason == Validation) changeUsertokensAndRetry(); // recovery else throw sql; } } catch(Exception e) { r.tellFailed(e.toString()); } Would then become: try { ... } catch(SqlException sql) if (sql.reason == Auth || sql.reason == Validation) { changeUsertokensAndRetry(); } catch(Exception e) { r.tellFailed(e.toString()); } instead of one giant catch block that catches all exceptions. Basically, it augments the code that determines where the exception is caught to check for more than just type. But I don't know how common stuff like that is. -SteveI think in this case, ValidationException and AuthException might share a common parent (SqlException) which you do NOT want to catch. It is advantageous in this case to have both a hierarchy through inheritance and a hierarchy through parameters. Here's another idea, to avoid rethrows, what about some pre-handler code that tests if an exception is what you want? Perhaps the same mechanism that is used by template constraints: catch(SqlException e) if (e.reason is Auth || e.reason is Validation) { r.tellFailed(e.toString()); }I think we're a bit too immersed in the "what can we add to the language". In this case, for example, I see no reason for the "if" to be moved inside and call it a day.
Oct 23 2008
Thu, 23 Oct 2008 14:44:46 -0500, Andrei Alexandrescu wrote:Sorry, I meant to catch Exception. My point was, if I want to print an informative message, the exception should be able to provide it without having to encode it in its type.It's all nice and simple until you want to localize. Then all your 'informative compiler-provided messages' appear as garbage to a non- English-speaking user. They need to be translated somehow. And the translation is likely to be based upon the context, not upon an arbitrary string exception contains.
Oct 23 2008
On Fri, Oct 24, 2008 at 6:41 AM, Sergey Gromov <snake.scaly gmail.com> wrote:Thu, 23 Oct 2008 14:44:46 -0500, Andrei Alexandrescu wrote:Just use poedit or whatever to provide localizations of the messages. I don't see how this has bearing on the discussion at all. --bbSorry, I meant to catch Exception. My point was, if I want to print an informative message, the exception should be able to provide it without having to encode it in its type.It's all nice and simple until you want to localize. Then all your 'informative compiler-provided messages' appear as garbage to a non- English-speaking user. They need to be translated somehow. And the translation is likely to be based upon the context, not upon an arbitrary string exception contains.
Oct 23 2008
Fri, 24 Oct 2008 06:55:27 +0900, Bill Baxter wrote:On Fri, Oct 24, 2008 at 6:41 AM, Sergey Gromov <snake.scaly gmail.com> wrote:Where do I get all the messages library may throw? How can I be sure that the message won't change in the next release, silently discarding my translation? Informative library-provided messages are a myth. The only informative part is an exception type, or a standardized error code--which is even better for localization. The "writeln(e.toString())" approach only suffices for quick utilities not meant for use by an end user.Thu, 23 Oct 2008 14:44:46 -0500, Andrei Alexandrescu wrote:Just use poedit or whatever to provide localizations of the messages. I don't see how this has bearing on the discussion at all.Sorry, I meant to catch Exception. My point was, if I want to print an informative message, the exception should be able to provide it without having to encode it in its type.It's all nice and simple until you want to localize. Then all your 'informative compiler-provided messages' appear as garbage to a non- English-speaking user. They need to be translated somehow. And the translation is likely to be based upon the context, not upon an arbitrary string exception contains.
Oct 23 2008
On Fri, Oct 24, 2008 at 7:45 AM, Sergey Gromov <snake.scaly gmail.com> wrote:Fri, 24 Oct 2008 06:55:27 +0900, Bill Baxter wrote:Ah, I see your point now. I thought this was still about making distinct types for every exception. I missed the comment from Andrei. --bbOn Fri, Oct 24, 2008 at 6:41 AM, Sergey Gromov <snake.scaly gmail.com> wrote:Where do I get all the messages library may throw?Thu, 23 Oct 2008 14:44:46 -0500, Andrei Alexandrescu wrote:Just use poedit or whatever to provide localizations of the messages. I don't see how this has bearing on the discussion at all.Sorry, I meant to catch Exception. My point was, if I want to print an informative message, the exception should be able to provide it without having to encode it in its type.It's all nice and simple until you want to localize. Then all your 'informative compiler-provided messages' appear as garbage to a non- English-speaking user. They need to be translated somehow. And the translation is likely to be based upon the context, not upon an arbitrary string exception contains.
Oct 23 2008
Sergey Gromov wrote:Fri, 24 Oct 2008 06:55:27 +0900, Bill Baxter wrote:I agree. For true localization, string tables are necessary. AndreiOn Fri, Oct 24, 2008 at 6:41 AM, Sergey Gromov <snake.scaly gmail.com> wrote:Where do I get all the messages library may throw? How can I be sure that the message won't change in the next release, silently discarding my translation? Informative library-provided messages are a myth. The only informative part is an exception type, or a standardized error code--which is even better for localization. The "writeln(e.toString())" approach only suffices for quick utilities not meant for use by an end user.Thu, 23 Oct 2008 14:44:46 -0500, Andrei Alexandrescu wrote:Just use poedit or whatever to provide localizations of the messages. I don't see how this has bearing on the discussion at all.Sorry, I meant to catch Exception. My point was, if I want to print an informative message, the exception should be able to provide it without having to encode it in its type.It's all nice and simple until you want to localize. Then all your 'informative compiler-provided messages' appear as garbage to a non- English-speaking user. They need to be translated somehow. And the translation is likely to be based upon the context, not upon an arbitrary string exception contains.
Oct 23 2008
Sergey Gromov wrote:Thu, 23 Oct 2008 14:44:46 -0500, Andrei Alexandrescu wrote:No, translation would have to be provided via a string table. And guess who provides the key for that table. AndreiSorry, I meant to catch Exception. My point was, if I want to print an informative message, the exception should be able to provide it without having to encode it in its type.It's all nice and simple until you want to localize. Then all your 'informative compiler-provided messages' appear as garbage to a non- English-speaking user. They need to be translated somehow. And the translation is likely to be based upon the context, not upon an arbitrary string exception contains.
Oct 23 2008
On Fri, Oct 24, 2008 at 6:47 AM, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:Sergey Gromov wrote:But what Sergey is pointing out is that 1) if you rely on a human readable string for the key, then you have to fix things when some maintenance programmer fixes a spelling error in the message 2) if you rely on human readable strings in that are in 3rd party libraries then you have to find all those strings some how. Could be difficult without source. So if you're going to translate then having an actual key, a unique identifying symbol not meant for human consumption, is a better approach. --bbThu, 23 Oct 2008 14:44:46 -0500, Andrei Alexandrescu wrote:No, translation would have to be provided via a string table. And guess who provides the key for that table.Sorry, I meant to catch Exception. My point was, if I want to print an informative message, the exception should be able to provide it without having to encode it in its type.It's all nice and simple until you want to localize. Then all your 'informative compiler-provided messages' appear as garbage to a non- English-speaking user. They need to be translated somehow. And the translation is likely to be based upon the context, not upon an arbitrary string exception contains.
Oct 23 2008
Fri, 24 Oct 2008 08:54:49 +0900, Bill Baxter wrote:On Fri, Oct 24, 2008 at 6:47 AM, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:Correct. Thank you for putting this together. But there is even more to it than that: the library exceptions are usually too low-level and too specific to spit at the user as is. They need to be analysed and converted into a more appropriate form or action. And exception must provide means for such analysis other than message string parsing.Sergey Gromov wrote:But what Sergey is pointing out is that 1) if you rely on a human readable string for the key, then you have to fix things when some maintenance programmer fixes a spelling error in the message 2) if you rely on human readable strings in that are in 3rd party libraries then you have to find all those strings some how. Could be difficult without source. So if you're going to translate then having an actual key, a unique identifying symbol not meant for human consumption, is a better approach.Thu, 23 Oct 2008 14:44:46 -0500, Andrei Alexandrescu wrote:No, translation would have to be provided via a string table. And guess who provides the key for that table.Sorry, I meant to catch Exception. My point was, if I want to print an informative message, the exception should be able to provide it without having to encode it in its type.It's all nice and simple until you want to localize. Then all your 'informative compiler-provided messages' appear as garbage to a non- English-speaking user. They need to be translated somehow. And the translation is likely to be based upon the context, not upon an arbitrary string exception contains.
Oct 23 2008
Sergey Gromov wrote:Fri, 24 Oct 2008 08:54:49 +0900, Bill Baxter wrote:Right -- and what action the program was taking to cause the exception also must be taken into account.On Fri, Oct 24, 2008 at 6:47 AM, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:Correct. Thank you for putting this together. But there is even more to it than that: the library exceptions are usually too low-level and too specific to spit at the user as is. They need to be analysed and converted into a more appropriate form or action. And exception must provide means for such analysis other than message string parsing.Sergey Gromov wrote:But what Sergey is pointing out is that 1) if you rely on a human readable string for the key, then you have to fix things when some maintenance programmer fixes a spelling error in the message 2) if you rely on human readable strings in that are in 3rd party libraries then you have to find all those strings some how. Could be difficult without source. So if you're going to translate then having an actual key, a unique identifying symbol not meant for human consumption, is a better approach.Thu, 23 Oct 2008 14:44:46 -0500, Andrei Alexandrescu wrote:No, translation would have to be provided via a string table. And guess who provides the key for that table.Sorry, I meant to catch Exception. My point was, if I want to print an informative message, the exception should be able to provide it without having to encode it in its type.It's all nice and simple until you want to localize. Then all your 'informative compiler-provided messages' appear as garbage to a non- English-speaking user. They need to be translated somehow. And the translation is likely to be based upon the context, not upon an arbitrary string exception contains.
Oct 23 2008
Andrei Alexandrescu wrote:Sean Kelly wrote:Hm... you're right. So here we really have two classes of exceptions, one concerning the request itself and another concerning meta issues like connection failures. Meta issues can all be caught together as Exception, so the only specialized handler would be in handleRequest() as something like: catch( RequestException e ) { r.tellFailed( e.toString ); } Really, all I was getting at is that I don't think it's a good idea for there to be no type distinctions at all. The tricky thing, as you've clearly pointed out, is to distill those distinctions to only the pertinent ones rather than simply designating a new type for every error. SeanAndrei Alexandrescu wrote:Thanks for fueling my argument. There's duplication in code examples, as in many other examples I've seen in favor of by-type handling. First example: catch( Exception e ) { if (e.origin = "sql") connected = false; log( e ); } Less code and no duplication. Second example is even starker: catch( AuthException e ) { r.tellFailed( e.toString ); } Clearly the need is to factor in the message to print in the exception, at least in this case and many like it.Robert Fraser wrote:It may be different in a user application, but in services it's fairly common to have specialized code for handling different exception types. And more importantly, it's common to want different exception types to propagate to different levels for handling. Sure, one could use a generic exception handler at each level that rethrows if the detected type isn't one that handler cares about but why do this when filtering on type is a language feature? For example, let's say I have a network service that's backed by a SQL database. My main program loop may look something like this: bool connected = false; while( true ) { try { while( true ) { auto r = acceptRequest(); scope(failure) r.tellFailed(); if( !connected ) connectToDB(); handleRequest( r ); } } catch( SqlException e ) { connected = false; log( e ); } catch( Exception e ) { log( e ); } } ... void handleRequest( Request r ) { scope(failure) r.tellFailed( "General error" ); try { // process r } catch( AuthException e ) { r.tellFailed( "Authentication failure" ); } catch( ValidationException e ) { r.tellFailed( "Invalid request format" ); } } Being able to trap specific types of exceptions makes this code cleaner and more succinct than it would be otherwise. If this weren't possible I'd have to trap, check, and rethrow certain exceptions at different levels to ensure that the proper handler saw them.Option B: --------- try { new Socket(30587); } catch(Exception e) { if(e.type == ExceptionType.Socket) printf("Could not open socket\n"); else throw e; }I think you'd be hard-pressed to justify the "if" inside the second example. You couldn't create a Socket, period. It doesn't matter where exactly the exception was generated from. That's one thing about large exception hierarchies: everybody can come with cute examples on how they could be useful. As soon as the rubber hits the road, however, differentiating exceptions by type becomes useless.
Oct 23 2008
Sean Kelly wrote:Really, all I was getting at is that I don't think it's a good idea for there to be no type distinctions at all. The tricky thing, as you've clearly pointed out, is to distill those distinctions to only the pertinent ones rather than simply designating a new type for every error.Well put. But I think it's way more effective to start conservatively (with few exception types) and fan out, instead of as it is now - the first thing to be found in each std/ file ever is emperor's hairy belly pretending it's wearing a great cardigan. In fact, by this I'm requesting community's permission to throw (sic!) a large fraction of the exception classes out of Phobos. Andrei
Oct 23 2008
Andrei Alexandrescu wrote:r.tellFailed( e.toString );Now that's just wrong. toString should be used for internal debugging purposes. If there's a recoverable error and you want to show it to the user, in a big product, it will need to be internationalized. The worry about what language to display the string in should not be given to the exception thrower, it should be given to the catcher.
Oct 23 2008
Andrei Alexandrescu wrote:Robert Fraser wrote:So in most cases you don't need it... But why throw it out for the cases in which you do (or make it harder to use). In other words, is there any _harm_ being done by having a large exception hierarchy?Andrei Alexandrescu wrote:I think you'd be hard-pressed to justify the "if" inside the second example. You couldn't create a Socket, period. It doesn't matter where exactly the exception was generated from. That's one thing about large exception hierarchies: everybody can come with cute examples on how they could be useful. As soon as the rubber hits the road, however, differentiating exceptions by type becomes useless. AndreiJarrett Billingsley wrote:Yes, you _could_ use a field... but the "catch a subclass" style is already there and is supported by the language, so _why_ use a field? Which of the following is easier?: Option A: --------- try { new Socket(30587); } catch(SocketException e) { printf("Could not open socket\n"); } Option B: --------- try { new Socket(30587); } catch(Exception e) { if(e.type == ExceptionType.Socket) printf("Could not open socket\n"); else throw e; }On Wed, Oct 22, 2008 at 6:49 AM, Jacob Carlborg <doobnet gmail.com> wrote:I agree. In fact I wanted to ask you all the following question. What do you think about the current exception hierarchy in phobos? I think it is terrible. Each module in std you open, the first piece of code to be seen is the "class ThisModuleNameException" definition. In many (most?) cases the module-specific exception does absolutely nothing in addition to its base class. The putative reader (including me) tends to scroll non-critically over that passage without even blinking, mumbling in a trance - of course, yes, each module should define at least one exception type. Until one day when you stop scrolling and say, wait a minute. This all is repetition. And there are alternatives to catching by type - you can catch the base type and consult a field. And in fact I don't remember seeing code that depends on exceptions thrown from different modules having different types. There's something wrong here! I think most exception classes in phobos should be yanked if it's possible for their functionality (often nil) to be moved in the Exception base class. The module name should be a member. If someone needs to deal with an exception thrown from a specific module, they can always inspect the field. We don't need a huge hierarchy for that. AndreiI think the name ArrayBoundsException should be changed to a more general name like BoundsException, OutOfBoundsException or IndexOutOfBoundsException. Then you can use the exception in every class that have some sort of index operation and not just for an array/array class.2nded.
Oct 23 2008
Denis Koroskin Wrote:Leave the user unaware that an out of memory error has been occured and recovered from is my best wish.Ridiculous. I saw applications running out of memory. This is not something user can be unaware of. If you really want to recover from OutOfMemoryException or ProcessorNotFoundException no one prevents you from doing this, go catch it, hack it and continue execution. BTW if you want to operate with terabytes of data may be you need some special solution for this? Some applications have abilities to manipulate data of such volumes. :)
Oct 24 2008
Agreed. Either that, or superclasss it. - Bent "Jacob Carlborg" <doobnet gmail.com> skrev i meddelelsen news:gdn0ft$u2m$1 digitalmars.com...I think the name ArrayBoundsException should be changed to a more general name like BoundsException, OutOfBoundsException or IndexOutOfBoundsException. Then you can use the exception in every class that have some sort of index operation and not just for an array/array class.
Oct 26 2008