April 12, 2005
>> OutOfMemory is practically unrecoverable, but should not be
>> classed
>> as an unrecoverable exception.
>
> Agreed, in part, why "class" it as anything but what it is?
>
>> Conversely, AssertionFailure is practically recoverable, but most certainly should be classed as unrecoverable.
>
> As above, why "class" it as anything but what it is?

Because there has to be a common type that's catchable, and I don't think Object is the appropriate choice.

>> (And the language
>> should mandate and enforce the irrecoverability.)
>
> Disagree.

For reasons so blindingly obvious/insightful that you needn't specify them, I guess.



April 12, 2005
On Tue, 12 Apr 2005 16:23:06 +1000, Matthew <admin@stlsoft.dot.dot.dot.dot.org> wrote:
>>> OutOfMemory is practically unrecoverable, but should not be
>>> classed
>>> as an unrecoverable exception.
>>
>> Agreed, in part, why "class" it as anything but what it is?
>>
>>> Conversely, AssertionFailure is practically recoverable, but most
>>> certainly should be classed as unrecoverable.
>>
>> As above, why "class" it as anything but what it is?
>
> Because there has to be a common type that's catchable, and I don't
> think Object is the appropriate choice.

So.. you want:

Catchable
  Recoverable
    OutOfMemory
  NonRecoverable
    AssertionFailure

?

>>> (And the language
>>> should mandate and enforce the irrecoverability.)
>>
>> Disagree.
>
> For reasons so blindingly obvious/insightful that you needn't
> specify them, I guess.

Sarcasm is the lowest form of wit.

Why do you need to force a program to terminate? If the programmer wants to continue and can do so, they will, if not, they wont. I see no need to enforce it.

Regan
April 12, 2005
Matthew wrote:
>>>OutOfMemory is practically unrecoverable, but should not be classed
>>>as an unrecoverable exception.
>>
>>Agreed, in part, why "class" it as anything but what it is?
>>
>>
>>>Conversely, AssertionFailure is practically recoverable, but most
>>>certainly should be classed as unrecoverable.
>>
>>As above, why "class" it as anything but what it is?
> 
> 
> Because there has to be a common type that's catchable, and I don't think Object is the appropriate choice.
> 
> 
>>>(And the language
>>>should mandate and enforce the irrecoverability.)
>>
>>Disagree.
> 
> 
> For reasons so blindingly obvious/insightful that you needn't specify them, I guess.

IMO mandating this, that, and the other thing isn't necessarily the D-style. If someone for whatever crazy (and/or genius) reason wants to try to recover from what would usually be considered irrecoverable error, why does the compiler need to stop them?

Here's a possibly insane example. I'm trying to imagine a situation where it might be useful to try to make an irrevoverable error recoverable. Let's say you're using someone else's library (no source provided except headers). The library's pretty useful in some respects, but it has some stupid assert that don't make any sense and halts the program. Well, if the compiler won't let you try to recover after the assert then you might have to give up (it was a long shot anyways). Sure, it's not "proper programming practice" to subvert the library author's asserts, but sometimes "it kind of works" is all you need. D should be the kind of language that allows creativity.

-- 
jcc7
http://jcc_7.tripod.com/d/
April 12, 2005
"Regan Heath" <regan@netwin.co.nz> wrote in message news:opso3x5rhn23k2f5@nrage.netwin.co.nz...
> On Tue, 12 Apr 2005 16:23:06 +1000, Matthew <admin@stlsoft.dot.dot.dot.dot.org> wrote:
>>>> OutOfMemory is practically unrecoverable, but should not be
>>>> classed
>>>> as an unrecoverable exception.
>>>
>>> Agreed, in part, why "class" it as anything but what it is?
>>>
>>>> Conversely, AssertionFailure is practically recoverable, but
>>>> most
>>>> certainly should be classed as unrecoverable.
>>>
>>> As above, why "class" it as anything but what it is?
>>
>> Because there has to be a common type that's catchable, and I
>> don't
>> think Object is the appropriate choice.
>
> So.. you want:
>
> Catchable
>   Recoverable
>     OutOfMemory
>   NonRecoverable
>     AssertionFailure

You've changed the names of things - Catchable<=>Throwable, NonRecoverable <=> Unrecoverable <=> Irrecoverable - which is perfectly fine. I'm not allied to them.

You're close to what I'm thinking. Using your terms

 Catchable
   Recoverable
      FileNotFoundException
   NonRecoverable
     AssertionFailure

But, as I said in a previous post, I think the jury's still out on OutOfMemory. I've a strong suspicion it should fall out as being an exception, but I think there's some mileage in discussing whether it might have another 'type', e.g. ResourceExhaustion. Reason being that, though memory exhaustion is in principle recoverable, in practice it is not recoverable (since getting memory to throw/handle is tricky, and may require workarounds) and also often so unlikely as to make it not worth worrying about.

So, the conversation I'm interesting in seeing is whether these characteristics of OutOfMemory are shared by any other resource exhaustion. If so, it might be worth our while to do something different. After all, a file not being present can be a 'normal' (from a user's perspective) runtime condition, whereas memory exhaustion is likely to be seen otherwise, even though both are, in principle, recoverable.

One that comes to mind is threading keys and/or slots. Whether Win32 TLS or PTHREADS TSD, inability to allocate a TSS key, or aquire a slot for an allocated key, is a pretty terminal condition. More so, than running out memory, in fact, although the shutdown might be more graceful.

So, I see the taxonomy as being either (now using my/Ben's names):

Object <= not throwable, btw
    Throwable
        Error <= Unrecoverable exceptions
            ContractViolation
            Assertion
        Exception
            FileNotFoundException
            XMLParseException
        Exhaustion
            MemoryExhaustion
            TSSKeyExhaustion

or, if we just lump exhaustions in with exceptions

Object <= not throwable, btw
    Throwable
        Error <= Unrecoverable exceptions
            ContractViolation
            Assertion
        Exception
            FileNotFoundException
            XMLParseException
            MemoryExhaustionException
            TSSKeyExhaustionException


>>>> (And the language
>>>> should mandate and enforce the irrecoverability.)
>>>
>>> Disagree.
>>
>> For reasons so blindingly obvious/insightful that you needn't specify them, I guess.
>
> Sarcasm is the lowest form of wit.

Maybe so, but unstubstantiated opinion is worth precisely nothing. It's an inconsiderate waste of other people's time.

> Why do you need to force a program to terminate? If the programmer wants  to continue and can do so, they will, if not, they wont. I see no need to  enforce it.

There are several flaws suggested in your understanding of the issue by just those two sentences.


First, "Why do you need to force a program to terminate?". This one's simple: The program must be forced to terminate because it has violated its design. (Let me digress for a moment and confess that before I made the leap into CP-grok-ville this never seemed simple, or at least never cut and dried.)

What's at issue here is not that the program has encountered a runtime error, or even (the very poorly termed) "unexpected situation". What a contract violation states is _precisely_ and _absolutely_ that a program has violated its design. An example from my recent work was that one of the server components, which served as an intermediate between three other components, should never have data in its input queues when not in a fully connected state. That is the expression of the design. (FYI: two of the other components with which it communicated were sockets based, whereas the third was a message queue.) When we put it into production all was well, until one component outside our control (another, much bigger (<g>) company was responsible for that) started sending up information through the message queue when it shouldn't.

What happened was that our process immediately cacked itself, and printed out a nice lot of information about "VIOLATION: downstream XYZ queue not empty in state ABC". Thus, this exposed that the implementation of the component was violating the design assumptions. The result of that immediate failure was an almost immediate realisation of the problem - in about 2 minutes, and a very rapid fix - about 90mins work, IIRC.

Now consider if the violation had been recoverable, which would certainly have been possible, since there was no memory corruption, and, indeed, no corruption of any of the internals of the component which violated. These systems produce a *lot* of logging output, and it's perfectly possible that a non-terminating log entry would have been missed. Furthermore, the error would have manifested considerably later, after the now out-of-date messages from the downstream queue was passed up through our components and out into the outside world. Given the fact that several companies were frantically involved in updating networking protocols and architectures simultaneously, that bug could have lain dormant for days, weeks, or even months. That would have cost both customers and the client a lot of money, and also cost us some reputation.


Second: "If the programmer wants to continue and can do so, they will, if not, they wont". Who's the programmer? Do you mean the user? Do you think that the end users of (even a substantial proportion of) systems are programmers? That suggests a significantly skewed perspective and, I'm afraid to say, implies that your experience is of programming for programmers, rather than more "commercial" activities. There's nothing wrong with that, to be sure, but it can't provide a base of experience suitable for making fundamental decisions on language design issues with very wide ramifications.


But let's give you the benefit of the doubt, and assume you misspoke, and actually meant: "If the [user] wants to continue and can do so, they will, if not, they wont". This one's even more simple than the first: There often isn't a user, or the user is significantly divorced from the error, separated by threads/processes/machines/networks. Even when there is a user, I suggest it's highly undesirable to leave it to them, highly ignorant of the specifics of your program (and, probably, of computers / software engineering in general) to have to attempt to handle something that's now operating outside the bounds of its design. It's analogous to selling someone a car and, when its brakes fail, telling them to drive on at their own risk.


Notwithstanding all the foregoing, there's a much more fundamental, albeit little recognised, issue. Computers make a strict interpretation of what we, the programmers, instruct them to do. Now a contract violation, as I've said, is pure and simple a statement that your instructions to the computer (or to the compiler, if you will) are fundamentally flawed. Since computers do not have redundancy, intuition, instincts, sixth-sense, a friend to call, or any other "higher order" functioning, there are exactly two things a process can do in that circumstance. It can operate in a fundamentally flawed manner, or it can stop. THERE ARE NO OTHER OPTIONS. And _that_ is the crux of the matter. Unless and until a programmer grasps that concept, they can't grok CP. There's no shame in not having doing so. I did 10 years of commercial programming, much of it very successful, thank you very much, before I saw the light (and I could name you some super famous chaps who're still a bit wooly on it). But I can absolutely aver that programming using strict CP results in faster development time, *far* more robust product, and happier clients and developers alike.


Matthew



April 12, 2005
"J C Calvarese" <jcc7@cox.net> wrote in message news:d3fspo$1u0j$1@digitaldaemon.com...
> Matthew wrote:
>>>>OutOfMemory is practically unrecoverable, but should not be
>>>>classed
>>>>as an unrecoverable exception.
>>>
>>>Agreed, in part, why "class" it as anything but what it is?
>>>
>>>
>>>>Conversely, AssertionFailure is practically recoverable, but
>>>>most
>>>>certainly should be classed as unrecoverable.
>>>
>>>As above, why "class" it as anything but what it is?
>>
>>
>> Because there has to be a common type that's catchable, and I don't think Object is the appropriate choice.
>>
>>
>>>>(And the language
>>>>should mandate and enforce the irrecoverability.)
>>>
>>>Disagree.
>>
>>
>> For reasons so blindingly obvious/insightful that you needn't specify them, I guess.
>
> IMO mandating this, that, and the other thing isn't necessarily the D-style. If someone for whatever crazy (and/or genius) reason wants to try to recover from what would usually be considered irrecoverable error, why does the compiler need to stop them?

There are two parts to this:

1. Implicit in your argument is that the "programmer knows best in *all* possible circumstances". I can tell you that, as someone who's worked for over 10 years, written 1.5 books, and worked on some very successful high risk projects, the one thing I'm sure of is that I do _not_ know everything, and I do not always know best. I learn something new from more experienced people at least once a month. I understand that D has come from the C school where freedom of expression (both micro and macro) is valued highly, and is also attracting Linux types by whom freedom in all its facets is prized most high. In fact I share a lot of that instinct and sentiment. But the fact of the matter is that there are very good reasons - espoused by people loftier than I - for irrecoverability, and no reasons for not having it save for some ephemeral notion of "freedom".

2. As I've demonstrated with the STLSoft library's unrecoverable class, implementing irrecoverability can be done easily and effectively in C++ in the form of a library which one may opt to use or not use at ones own discretion. If we would do the same in D, there'd be some reason for not having it built into the language. However, the reason it can work in C++ is that one can (and should) throw by value - and catch by reference, of course - and the death tractors of exception objects are invoked in a deterministic manner. However, in D exceptions are thrown by reference, and their destructors are useless. There is, therefore, no mechanism for a library solution to irrecoverability in D. Therefore, we need a language-based solution.

> Here's a possibly insane example. I'm trying to imagine a situation where it might be useful to try to make an irrevoverable error recoverable. Let's say you're using someone else's library (no source provided except headers). The library's pretty useful in some respects, but it has some stupid assert that don't make any sense and halts the program. Well, if the compiler won't let you try to recover after the assert then you might have to give up (it was a long shot anyways). Sure, it's not "proper programming practice" to subvert the library author's asserts, but sometimes "it kind of works" is all you need. D should be the kind of language that allows creativity.

It's wrongheaded, I'm afraid. If you fire an assert in a library then you're using it counter to its design. If (the expression of) its design is wrong, i.e. the assert shouldn't be there, then you've got even bigger problems, and any use of it you make which is counter to its design cannot be characterised to be anything else. Two wrongs cannot make a right.

AFAIK - and I've been discussing this subject with friends and colleagues in various settings for a long while - there's only one scenario where irrecoverability (for CP violations) makes sense: Debuggers. I absolutely want D to support debuggers correctly, but I don't accept that the real and significant advantages of irrecoverability have to be sacrified for that.

Nonetheless, I do have serious doubts that irrecoverability will be incorporated into D, since Walter tends to favour "good enough" solutions rather than aiming for strict/theoretical best, and because the principles and advantages of irrecoverability are not yet sufficiently mainstream. It's a pity though, because it'd really lift D's head above its peers. (And without it, there'll be another area in which C++ will continue to be able to claim supremacy, because D cannot support it in library form.)

Cheers

Matthew


April 12, 2005
Not that I disagree, in principle, but there are still cases where you'd want to recover from an "unrecoverable" error. Consider an environment like Eclipse, which is built totally out of plugins, and there can be hundreds of them. What you're saying is that whenever one of those faults, the whole system should abort, which is definitely not what I'd want it to do.

I mean, when I do something like inspect a value in a debugger, and the value is 150MB and the debugger runs out of memory, I don't want it to stop, just because it can't show me a var (which can just as easily manifest as an assertion error or whatever)...

Enforcing unrecoverability would be a mistake, if you ask me, although I totally support an exception hierarchy that would make "unrecoverable" errors something people wouldn't try to catch normally.


xs0


Matthew wrote:
> "Regan Heath" <regan@netwin.co.nz> wrote in message news:opso3x5rhn23k2f5@nrage.netwin.co.nz...
> 
>>On Tue, 12 Apr 2005 16:23:06 +1000, Matthew <admin@stlsoft.dot.dot.dot.dot.org> wrote:
>>
>>>>>OutOfMemory is practically unrecoverable, but should not be
>>>>>classed
>>>>>as an unrecoverable exception.
>>>>
>>>>Agreed, in part, why "class" it as anything but what it is?
>>>>
>>>>
>>>>>Conversely, AssertionFailure is practically recoverable, but most
>>>>>certainly should be classed as unrecoverable.
>>>>
>>>>As above, why "class" it as anything but what it is?
>>>
>>>Because there has to be a common type that's catchable, and I don't
>>>think Object is the appropriate choice.
>>
>>So.. you want:
>>
>>Catchable
>>  Recoverable
>>    OutOfMemory
>>  NonRecoverable
>>    AssertionFailure
> 
> 
> You've changed the names of things - Catchable<=>Throwable, NonRecoverable <=> Unrecoverable <=> Irrecoverable - which is perfectly fine. I'm not allied to them.
> 
> You're close to what I'm thinking. Using your terms
> 
>  Catchable
>    Recoverable
>       FileNotFoundException
>    NonRecoverable
>      AssertionFailure
> 
> But, as I said in a previous post, I think the jury's still out on OutOfMemory. I've a strong suspicion it should fall out as being an exception, but I think there's some mileage in discussing whether it might have another 'type', e.g. ResourceExhaustion. Reason being that, though memory exhaustion is in principle recoverable, in practice it is not recoverable (since getting memory to throw/handle is tricky, and may require workarounds) and also often so unlikely as to make it not worth worrying about.
> 
> So, the conversation I'm interesting in seeing is whether these characteristics of OutOfMemory are shared by any other resource exhaustion. If so, it might be worth our while to do something different. After all, a file not being present can be a 'normal' (from a user's perspective) runtime condition, whereas memory exhaustion is likely to be seen otherwise, even though both are, in principle, recoverable.
> 
> One that comes to mind is threading keys and/or slots. Whether Win32 TLS or PTHREADS TSD, inability to allocate a TSS key, or aquire a slot for an allocated key, is a pretty terminal condition. More so, than running out memory, in fact, although the shutdown might be more graceful.
> 
> So, I see the taxonomy as being either (now using my/Ben's names):
> 
> Object <= not throwable, btw
>     Throwable
>         Error <= Unrecoverable exceptions
>             ContractViolation
>             Assertion
>         Exception
>             FileNotFoundException
>             XMLParseException
>         Exhaustion
>             MemoryExhaustion
>             TSSKeyExhaustion
> 
> or, if we just lump exhaustions in with exceptions
> 
> Object <= not throwable, btw
>     Throwable
>         Error <= Unrecoverable exceptions
>             ContractViolation
>             Assertion
>         Exception
>             FileNotFoundException
>             XMLParseException
>             MemoryExhaustionException
>             TSSKeyExhaustionException
> 
> 
> 
>>>>>(And the language
>>>>>should mandate and enforce the irrecoverability.)
>>>>
>>>>Disagree.
>>>
>>>For reasons so blindingly obvious/insightful that you needn't
>>>specify them, I guess.
>>
>>Sarcasm is the lowest form of wit.
> 
> 
> Maybe so, but unstubstantiated opinion is worth precisely nothing. It's an inconsiderate waste of other people's time.
> 
> 
>>Why do you need to force a program to terminate? If the programmer wants  to continue and can do so, they will, if not, they wont. I see no need to  enforce it.
> 
> 
> There are several flaws suggested in your understanding of the issue by just those two sentences.
> 
> 
> First, "Why do you need to force a program to terminate?". This one's simple: The program must be forced to terminate because it has violated its design. (Let me digress for a moment and confess that before I made the leap into CP-grok-ville this never seemed simple, or at least never cut and dried.)
> 
> What's at issue here is not that the program has encountered a runtime error, or even (the very poorly termed) "unexpected situation". What a contract violation states is _precisely_ and _absolutely_ that a program has violated its design. An example from my recent work was that one of the server components, which served as an intermediate between three other components, should never have data in its input queues when not in a fully connected state. That is the expression of the design. (FYI: two of the other components with which it communicated were sockets based, whereas the third was a message queue.) When we put it into production all was well, until one component outside our control (another, much bigger (<g>) company was responsible for that) started sending up information through the message queue when it shouldn't.
> 
> What happened was that our process immediately cacked itself, and printed out a nice lot of information about "VIOLATION: downstream XYZ queue not empty in state ABC". Thus, this exposed that the implementation of the component was violating the design assumptions. The result of that immediate failure was an almost immediate realisation of the problem - in about 2 minutes, and a very rapid fix - about 90mins work, IIRC.
> 
> Now consider if the violation had been recoverable, which would certainly have been possible, since there was no memory corruption, and, indeed, no corruption of any of the internals of the component which violated. These systems produce a *lot* of logging output, and it's perfectly possible that a non-terminating log entry would have been missed. Furthermore, the error would have manifested considerably later, after the now out-of-date messages from the downstream queue was passed up through our components and out into the outside world. Given the fact that several companies were frantically involved in updating networking protocols and architectures simultaneously, that bug could have lain dormant for days, weeks, or even months. That would have cost both customers and the client a lot of money, and also cost us some reputation.
> 
> 
> Second: "If the programmer wants to continue and can do so, they will, if not, they wont". Who's the programmer? Do you mean the user? Do you think that the end users of (even a substantial proportion of) systems are programmers? That suggests a significantly skewed perspective and, I'm afraid to say, implies that your experience is of programming for programmers, rather than more "commercial" activities. There's nothing wrong with that, to be sure, but it can't provide a base of experience suitable for making fundamental decisions on language design issues with very wide ramifications.
> 
> 
> But let's give you the benefit of the doubt, and assume you misspoke, and actually meant: "If the [user] wants to continue and can do so, they will, if not, they wont". This one's even more simple than the first: There often isn't a user, or the user is significantly divorced from the error, separated by threads/processes/machines/networks. Even when there is a user, I suggest it's highly undesirable to leave it to them, highly ignorant of the specifics of your program (and, probably, of computers / software engineering in general) to have to attempt to handle something that's now operating outside the bounds of its design. It's analogous to selling someone a car and, when its brakes fail, telling them to drive on at their own risk.
> 
> 
> Notwithstanding all the foregoing, there's a much more fundamental, albeit little recognised, issue. Computers make a strict interpretation of what we, the programmers, instruct them to do. Now a contract violation, as I've said, is pure and simple a statement that your instructions to the computer (or to the compiler, if you will) are fundamentally flawed. Since computers do not have redundancy, intuition, instincts, sixth-sense, a friend to call, or any other "higher order" functioning, there are exactly two things a process can do in that circumstance. It can operate in a fundamentally flawed manner, or it can stop. THERE ARE NO OTHER OPTIONS. And _that_ is the crux of the matter. Unless and until a programmer grasps that concept, they can't grok CP. There's no shame in not having doing so. I did 10 years of commercial programming, much of it very successful, thank you very much, before I saw the light (and I could name you some super famous chaps who're still a bit wooly on it). But I can absolutely aver that programming using strict CP results in faster development time, *far* more robust product, and happier clients and developers alike.
> 
> 
> Matthew
> 
> 
> 
April 12, 2005
On Tue, 12 Apr 2005 11:52:53 +0200, xs0 <xs0@xs0.com> wrote:
> Not that I disagree, in principle, but there are still cases where you'd want to recover from an "unrecoverable" error. Consider an environment like Eclipse, which is built totally out of plugins, and there can be hundreds of them. What you're saying is that whenever one of those faults, the whole system should abort, which is definitely not what I'd want it to do.
>
> I mean, when I do something like inspect a value in a debugger, and the value is 150MB and the debugger runs out of memory, I don't want it to stop, just because it can't show me a var (which can just as easily manifest as an assertion error or whatever)...
>
> Enforcing unrecoverability would be a mistake, if you ask me, although I totally support an exception hierarchy that would make "unrecoverable" errors something people wouldn't try to catch normally.

My sentiments exactly.

Regan

> Matthew wrote:
>> "Regan Heath" <regan@netwin.co.nz> wrote in message news:opso3x5rhn23k2f5@nrage.netwin.co.nz...
>>
>>> On Tue, 12 Apr 2005 16:23:06 +1000, Matthew <admin@stlsoft.dot.dot.dot.dot.org> wrote:
>>>
>>>>>> OutOfMemory is practically unrecoverable, but should not be
>>>>>> classed
>>>>>> as an unrecoverable exception.
>>>>>
>>>>> Agreed, in part, why "class" it as anything but what it is?
>>>>>
>>>>>
>>>>>> Conversely, AssertionFailure is practically recoverable, but most
>>>>>> certainly should be classed as unrecoverable.
>>>>>
>>>>> As above, why "class" it as anything but what it is?
>>>>
>>>> Because there has to be a common type that's catchable, and I don't
>>>> think Object is the appropriate choice.
>>>
>>> So.. you want:
>>>
>>> Catchable
>>>  Recoverable
>>>    OutOfMemory
>>>  NonRecoverable
>>>    AssertionFailure
>>   You've changed the names of things - Catchable<=>Throwable, NonRecoverable <=> Unrecoverable <=> Irrecoverable - which is perfectly fine. I'm not allied to them.
>>  You're close to what I'm thinking. Using your terms
>>   Catchable
>>    Recoverable
>>       FileNotFoundException
>>    NonRecoverable
>>      AssertionFailure
>>  But, as I said in a previous post, I think the jury's still out on OutOfMemory. I've a strong suspicion it should fall out as being an exception, but I think there's some mileage in discussing whether it might have another 'type', e.g. ResourceExhaustion. Reason being that, though memory exhaustion is in principle recoverable, in practice it is not recoverable (since getting memory to throw/handle is tricky, and may require workarounds) and also often so unlikely as to make it not worth worrying about.
>>  So, the conversation I'm interesting in seeing is whether these characteristics of OutOfMemory are shared by any other resource exhaustion. If so, it might be worth our while to do something different. After all, a file not being present can be a 'normal' (from a user's perspective) runtime condition, whereas memory exhaustion is likely to be seen otherwise, even though both are, in principle, recoverable.
>>  One that comes to mind is threading keys and/or slots. Whether Win32 TLS or PTHREADS TSD, inability to allocate a TSS key, or aquire a slot for an allocated key, is a pretty terminal condition. More so, than running out memory, in fact, although the shutdown might be more graceful.
>>  So, I see the taxonomy as being either (now using my/Ben's names):
>>  Object <= not throwable, btw
>>     Throwable
>>         Error <= Unrecoverable exceptions
>>             ContractViolation
>>             Assertion
>>         Exception
>>             FileNotFoundException
>>             XMLParseException
>>         Exhaustion
>>             MemoryExhaustion
>>             TSSKeyExhaustion
>>  or, if we just lump exhaustions in with exceptions
>>  Object <= not throwable, btw
>>     Throwable
>>         Error <= Unrecoverable exceptions
>>             ContractViolation
>>             Assertion
>>         Exception
>>             FileNotFoundException
>>             XMLParseException
>>             MemoryExhaustionException
>>             TSSKeyExhaustionException
>>
>>>>>> (And the language
>>>>>> should mandate and enforce the irrecoverability.)
>>>>>
>>>>> Disagree.
>>>>
>>>> For reasons so blindingly obvious/insightful that you needn't
>>>> specify them, I guess.
>>>
>>> Sarcasm is the lowest form of wit.
>>   Maybe so, but unstubstantiated opinion is worth precisely nothing. It's an inconsiderate waste of other people's time.
>>
>>> Why do you need to force a program to terminate? If the programmer wants  to continue and can do so, they will, if not, they wont. I see no need to  enforce it.
>>   There are several flaws suggested in your understanding of the issue by just those two sentences.
>>   First, "Why do you need to force a program to terminate?". This one's simple: The program must be forced to terminate because it has violated its design. (Let me digress for a moment and confess that before I made the leap into CP-grok-ville this never seemed simple, or at least never cut and dried.)
>>  What's at issue here is not that the program has encountered a runtime error, or even (the very poorly termed) "unexpected situation". What a contract violation states is _precisely_ and _absolutely_ that a program has violated its design. An example from my recent work was that one of the server components, which served as an intermediate between three other components, should never have data in its input queues when not in a fully connected state. That is the expression of the design. (FYI: two of the other components with which it communicated were sockets based, whereas the third was a message queue.) When we put it into production all was well, until one component outside our control (another, much bigger (<g>) company was responsible for that) started sending up information through the message queue when it shouldn't.
>>  What happened was that our process immediately cacked itself, and printed out a nice lot of information about "VIOLATION: downstream XYZ queue not empty in state ABC". Thus, this exposed that the implementation of the component was violating the design assumptions. The result of that immediate failure was an almost immediate realisation of the problem - in about 2 minutes, and a very rapid fix - about 90mins work, IIRC.
>>  Now consider if the violation had been recoverable, which would certainly have been possible, since there was no memory corruption, and, indeed, no corruption of any of the internals of the component which violated. These systems produce a *lot* of logging output, and it's perfectly possible that a non-terminating log entry would have been missed. Furthermore, the error would have manifested considerably later, after the now out-of-date messages from the downstream queue was passed up through our components and out into the outside world. Given the fact that several companies were frantically involved in updating networking protocols and architectures simultaneously, that bug could have lain dormant for days, weeks, or even months. That would have cost both customers and the client a lot of money, and also cost us some reputation.
>>   Second: "If the programmer wants to continue and can do so, they will, if not, they wont". Who's the programmer? Do you mean the user? Do you think that the end users of (even a substantial proportion of) systems are programmers? That suggests a significantly skewed perspective and, I'm afraid to say, implies that your experience is of programming for programmers, rather than more "commercial" activities. There's nothing wrong with that, to be sure, but it can't provide a base of experience suitable for making fundamental decisions on language design issues with very wide ramifications.
>>   But let's give you the benefit of the doubt, and assume you misspoke, and actually meant: "If the [user] wants to continue and can do so, they will, if not, they wont". This one's even more simple than the first: There often isn't a user, or the user is significantly divorced from the error, separated by threads/processes/machines/networks. Even when there is a user, I suggest it's highly undesirable to leave it to them, highly ignorant of the specifics of your program (and, probably, of computers / software engineering in general) to have to attempt to handle something that's now operating outside the bounds of its design. It's analogous to selling someone a car and, when its brakes fail, telling them to drive on at their own risk.
>>   Notwithstanding all the foregoing, there's a much more fundamental, albeit little recognised, issue. Computers make a strict interpretation of what we, the programmers, instruct them to do. Now a contract violation, as I've said, is pure and simple a statement that your instructions to the computer (or to the compiler, if you will) are fundamentally flawed. Since computers do not have redundancy, intuition, instincts, sixth-sense, a friend to call, or any other "higher order" functioning, there are exactly two things a process can do in that circumstance. It can operate in a fundamentally flawed manner, or it can stop. THERE ARE NO OTHER OPTIONS. And _that_ is the crux of the matter. Unless and until a programmer grasps that concept, they can't grok CP. There's no shame in not having doing so. I did 10 years of commercial programming, much of it very successful, thank you very much, before I saw the light (and I could name you some super famous chaps who're still a bit wooly on it). But I can absolutely aver that programming using strict CP results in faster development time, *far* more robust product, and happier clients and developers alike.
>>   Matthew
>>

April 12, 2005
On Tue, 12 Apr 2005 18:57:10 +1000, Matthew <admin@stlsoft.dot.dot.dot.dot.org> wrote:
> "Regan Heath" <regan@netwin.co.nz> wrote in message
> news:opso3x5rhn23k2f5@nrage.netwin.co.nz...
>> On Tue, 12 Apr 2005 16:23:06 +1000, Matthew
>> <admin@stlsoft.dot.dot.dot.dot.org> wrote:

<snip>

>>> Because there has to be a common type that's catchable, and I
>>> don't
>>> think Object is the appropriate choice.
>>
>> So.. you want:
>>
>> Catchable
>>   Recoverable
>>     OutOfMemory
>>   NonRecoverable
>>     AssertionFailure
>
> You've changed the names of things - Catchable<=>Throwable,
> NonRecoverable <=> Unrecoverable <=> Irrecoverable - which is
> perfectly fine. I'm not allied to them.

I was trying to reflect your statement above about wanting something 'catchable'.
Food for thought - Catchable (sorta) implies throwable, throwable doesn't (necesarily) imply catchable.

<snip>

> though memory exhaustion is in principle recoverable, in
> practice it is not recoverable (since getting memory to throw/handle
> is tricky, and may require workarounds) and also often so unlikely
> as to make it not worth worrying about.

The point Ben made in his original post (to which I agree) is that this is a per-application decision, it cannot be made "in general".

> So, the conversation I'm interesting in seeing is whether these
> characteristics of OutOfMemory are shared by any other resource
> exhaustion.

Like running out of operating system handles, file handles, socket handles...

<snip>

> So, I see the taxonomy as being either (now using my/Ben's names):
>
> Object <= not throwable, btw
>     Throwable
>         Error <= Unrecoverable exceptions
>             ContractViolation
>             Assertion
>         Exception
>             FileNotFoundException
>             XMLParseException
>         Exhaustion
>             MemoryExhaustion
>             TSSKeyExhaustion
>
> or, if we just lump exhaustions in with exceptions
>
> Object <= not throwable, btw
>     Throwable
>         Error <= Unrecoverable exceptions
>             ContractViolation
>             Assertion
>         Exception
>             FileNotFoundException
>             XMLParseException
>             MemoryExhaustionException
>             TSSKeyExhaustionException

So, in essence you just want to insert "throwable" in between object and the rest of the tree.

>> Why do you need to force a program to terminate? If the programmer
>> wants  to continue and can do so, they will, if not, they wont. I
>> see no need to  enforce it.

<snip>

> First, "Why do you need to force a program to terminate?". This
> one's simple: The program must be forced to terminate because it has
> violated its design.

Correction: The program *must* terminate *if* it has violated its design.

Do you know the design of a program someone is going to write in the future?

How can you say with utmost surety that under circumstance X that program has violated it's design and *must* terminate?

<snip>

> Second: "If the programmer wants to continue and can do so, they
> will, if not, they wont". Who's the programmer? Do you mean the
> user?

No.

<snip>

> But let's give you the benefit of the doubt, and assume you
> misspoke, and actually meant: "If the [user] wants to continue and
> can do so, they will, if not, they wont".

No, I did not mean that.

<snip>

> Notwithstanding all the foregoing, there's a much more fundamental,
> albeit little recognised, issue. Computers make a strict
> interpretation of what we, the programmers, instruct them to do. Now
> a contract violation, as I've said, is pure and simple a statement
> that your instructions to the computer (or to the compiler, if you
> will) are fundamentally flawed.

Correct, and if the program violates it's design it should terminate (in the most sensible way possible). However, none of this addresses the issue that you cannot know a future programs design nor whether it should terminate under any given 'exception'.

So as to clear any confusion, under what circumstance would you enforce program termination? in other words, which exception or error would you make un-catchable?

Regan
April 12, 2005
>> Maybe we could shorten these ArgumentExceptions to ArgExceptions or
>> ParamException since it's obvious what Arg and Param mean. So how about
>>      ParamException
>>        ParamNullException
>>        ParamRangeException
>>
>
> Just thinking about this, null and out of range are effectively the same thing, as null is "out of range" for a parameter that "cannot be null'. So we *could* just combine them.

The .Net doc explains that Range is for things that are non-null but still illegal (or for primitive types out of range). For example if a function takes a pointer to an int and the int must not be 5. I think it would be handy to have both. A null check is probably 75% of all input checking anyway - at least with a project with lots of classes.

> But then, of course, the reason for not combining them is so we can catch them seperately:
>
> void foo(int a){}
>
> try {
>   foo(5);
> } catch(ParamNullException e) {
> } catch(ParamRangeException e) {
> }
>
> Otherwise we could just say:
>
> class ParamException {
>   this(char[] param, char[] problem) {
>   }
> }
>
> And have it print "ParamException: (%s) is %s", eg:
> "ParamException: (a) is out of range"
> "ParamException: (a) is null"
> "ParamException: (a) is not my favourite number"
> "ParamException: (a) is unlucky for some"

If one doesn't care about the distinction between Null and Range then one can catch ParamException. It's true the string and printed exception would have the more detailed class name.

> <Warning: wacky idea>
> It's a pity the class tree isn't more 'obvious' then we could simply drop
> the redundant 'Exception' alltogether. eg.
>
> Exception
>   Parameter
>     Null
>     OutOfRange
>
> Is this:
>
> try {
> } catch(OutOfRange e) {
> }
>
> really that opaque that it requires this:
>
> try {
> } catch(ParamRangeException e) {
> }
>
> ?
>
> Of course, it then becomes possible to have collisions within the tree.
>
> Exception
>   Aaaaa
>     Here
>   Bbbbb
>     Here
>
> Exception.Aaaaa.Here
> Exception.Bbbbb.Here
>
> are both called "Here".
> </wacky idea>

This was suggested in the naming thread. It isn't that bad since the Here's can be distinguished by package and module names. Now that I think about it the Exception was used to indicate that it subclasses Exception, which seems useful.

ps - I mistakenly printed out those old threads and now I can symathize with Walter's statement that removing "dead quotes" from replies is useful - probably 75% or more of the printouts were lazy quoting that added nothing to the thread. One printout was 73 pages long.


April 12, 2005
>> So, I see the taxonomy as being either (now using my/Ben's names):
>>
>> Object <= not throwable, btw
>>     Throwable
>>         Error <= Unrecoverable exceptions
>>             ContractViolation
>>             Assertion
>>         Exception
>>             FileNotFoundException
>>             XMLParseException
>>         Exhaustion
>>             MemoryExhaustion
>>             TSSKeyExhaustion
>>
>> or, if we just lump exhaustions in with exceptions
>>
>> Object <= not throwable, btw
>>     Throwable
>>         Error <= Unrecoverable exceptions
>>             ContractViolation
>>             Assertion
>>         Exception
>>             FileNotFoundException
>>             XMLParseException
>>             MemoryExhaustionException
>>             TSSKeyExhaustionException
>
> So, in essence you just want to insert "throwable" in between object and  the rest of the tree.

Yes and, importantly, not allow anything not defined from Throwable to be thrown/caught.

> Do you know the design of a program someone is going to write in the  future?
>
> How can you say with utmost surety that under circumstance X that program  has violated it's design and *must* terminate?

Somewhere along the way we've had a gigantic disconnect. Maybe this stuff's new to you and I've assumed too much?

A programmer uses CP constructs - assertions, pre/postconditions, invariants - to assert truths about the logic of their program, i.e. that a given truth will hold if the program is behaving according to its design. So its not the case that _I_ say/know anything about the program's design, or any such fantastic thing, but that the programmer(s) know(s) the design as they're writing, and they _assert_ the truths about that design within the code.

>> Notwithstanding all the foregoing, there's a much more
>> fundamental,
>> albeit little recognised, issue. Computers make a strict
>> interpretation of what we, the programmers, instruct them to do.
>> Now
>> a contract violation, as I've said, is pure and simple a
>> statement
>> that your instructions to the computer (or to the compiler, if
>> you
>> will) are fundamentally flawed.
>
> Correct, and if the program violates it's design it should terminate (in  the most sensible way possible). However, none of this addresses the issue  that you cannot know a future programs design nor whether it should  terminate under any given 'exception'.

Hopefully I've now made that clear.

> So as to clear any confusion, under what circumstance would you enforce  program termination?

When a program violates its design, as detected by the assertions inserted into it by its creator(s). It must always do so.

> in other words, which exception or error would you  make un-catchable?

Sigh. I'm trying my best not to be rude, but it seems that you've really not bothered to read the posts in this thread before replying to them.

1. At no point have I _ever_ said anything was to be uncatchable.
Indeed, I've specifically, and regularly, discussed the action(s) to
be taken when catching an irrecoverable exception
2. As long as this debate's been going on, which, IIHIC, is the best
part of a year, the distinction between errors and exceptions has
been (ir)recoverability. By convention in D, an Exception is
recoverable and an Error is irrecoverable, but the latter is not
enforced, and, as I've shown not possible in D by library extension.

So, no exceptions would be irrecoverable. All errors would be irrecoverable. The only place, IMO, where there's a grey area is with resource exhaustion, which are theoretically recoverable (since they don't mean the program has violated its design) but are often practically irrecoverable (by virtue of the ramifications of the problem that's caused them).



1 2 3 4 5 6 7 8 9 10 11 12
Top | Discussion index | About this forum | D home