February 19, 2012
Le 19/02/2012 02:23, Jonathan M Davis a écrit :
> On Saturday, February 18, 2012 17:20:41 H. S. Teoh wrote:
>> On Sun, Feb 19, 2012 at 01:10:10AM +0000, Ben Davis wrote:
>> [...]
>>
>>> I guess this is a bit off topic, but what you probably want is
>>> syntactic sugar that says "declare constructors matching all super
>>> constructors and calling through to them" and can be used in ANY class
>>> hierarchy (not necessarily exceptions). For example:
>>>
>>> class Subtype : Supertype {
>>>
>>>      super all;
>>>
>>> }
>>>
>>> If you want to expose just specific constructors, then there could
>>> also be a shorthand for "declare a constructor matching a specific
>>> super constructor and calling through to it" - so you don't have to
>>> repeat all the arguments. For example:
>>>
>>> class Subtype : Supertype {
>>>
>>>      super();
>>>      super(string,int);
>>>
>>> }
>>>
>>> That would then make it an entirely separate issue and completely
>>> not Exception-specific.
>>
>> +1.
>>
>> This is definitely something not specific to Exception. Quite often, you
>> want to create a derived class overriding just one or two members of the
>> base class, but end up having to copy-n-paste most of the many ctors in
>> the base class along with their elaborate arguments just so you can pass
>> through the arguments to them.
>>
>> Having a way of simply saying "the ctors in this class default to the
>> base class ctors" will solve this problem in a very nice and logical
>> way. (I.e., you're sortof "inheriting the base class ctors", although
>> not exactly, of course.)
>
> Feel free to open a pull request. It would certainly be a useful feature for
> reducing boilerplate code in some class hierarchies (though in many, the
> constructors in the derived class must be different, in which case it wouldn't
> work).
>
> One potential issue though is that not all base classes necessarily share the
> same constructors. Which ones would be grabbed? The ones from the immediate
> base class? All of them? Only the ones common to all?
>
> - Jonathan M Davis

Well that should be achievable with compile time refexion and CTFE/mixin or mixin template. Maybe this should be inserted in phobos.
February 19, 2012
Le 19/02/2012 06:09, Jim Hewes a écrit :
> On 2/18/2012 5:59 PM, Robert Jacques wrote:
>> But you _always_ know what went wrong: An unexpected error occurred
>> while trying to do X, where X is whatever is inside the try-catch block.
>> Exceptions are for exceptional situations...
>
> Not to jump on you in particular for using the phrase "exceptions are
> for exceptional situations”, but I've always heard people say this in
> arguments about exceptions vs. returning error codes. Unfortunately
> those people usually never go on to define what exceptional situations
> are, so those trying to learn about using exceptions are left no better
> off. If exceptional cases are like divide-by-zero or hardware failures,
> then surely a bad parameter to a function is not “exceptional”. Then
> what? Is out-of-memory exceptional or something you should expect might
> happen given that memory is finite?
>
> I think of exception handling as tied to contract programming. A
> function has a specific job that it's supposed to do. If for any reason
> it cannot do that job successfully, an exception should be thrown. That
> can include even bad parameters (although if you have bad parameters to
> internal functions I'd think that is a design bug and could be handled
> by asserts). Look at the .NET library; it seems to work this way. So I
> think the term 'exceptional situations' has been kind of useless.
>

Well, I think you are messing up between contract and exception. Wrong parameters is a contract problem, not an exceptionnal situation.

The exemple you cited below is way more suited for an exception : someone unplug the USB device, then I trhow an Exception and it will cross all layers of my code to reach a point where it is recoverable.

Except that contract detail, your post make perfect sense.
February 19, 2012
On 2012-02-18 23:26, Jonathan M Davis wrote:
> On Saturday, February 18, 2012 20:20:23 deadalnix wrote:
>> I think your oppinion here is shaped by C++. For what I experienced, in
>> C++, exception are only usefull for very important problem you cannot
>> possibly solve, and at the best log the error and exit.
>>
>> An exemple is std::bad_alloc .
>>
>> However, in D, I think this is more the role of an Errors. Exception are
>> something « softer ». It will alert you on problems your program
>> encounter, but that are recoverable.
>>
>> You cannot recover from any exception at any place (sometime, you just
>> cannot at all).
>>
>> Let's get an exemple : your program ask a file to the user and do some
>> operations with this file. If the file doesn't exists, you can prompt
>> for another file to the user with a meaningful message and start again.
>> However, the first version of your program can just ignore that case and
>> fail with a less specific handler in firsts versions.
>>
>> You cannot achieve something like that if you don't have a useful type
>> to rely on. Here something like FileNotFoundException is what you want.
>>
>> The type of the exception must depend on the problem you are facing, not
>> on the module that trhow it. I see a lot of people doing the «
>> MyProgramException » or « MyLibException » but that doesn't make sense.
>> In this case, you are just making things harder.
>>
>> Back on the original subject, GetOptException is not what you want. As
>> getopt is supposed to handle command line parameters, you'll use
>> exception like : MissingParameterException, WrongFormatException,
>> UnknowParameterException or anything that is meaningful.
>>
>> Those Exceptions would inherit from something like CommandLineException.
>> This is useful because it describe what you are facing. Because you cant
>> to know what is the problem, not which piece of code face the problem.
>>
>> If this politic is choosen, then It would make sense to have several
>> modules of phobos throwing exceptions of the same type, or inheriting
>> from the same base class.
>>
>> Exception type is a convenient way to filter what you catch and what you
>> don't know how to handle at this point.
>
> In general, I agree with all of this. I very much think that having typed
> exceptions makes a lot of sense. In general, I think that Java got exceptions
> right (ignoring the issue with checked exceptions). Having typed exceptions
> works really well.
>
> In the case of getopt, what we want is a GetOptException which is for anything
> which goes wrong with getopt so that someone can catch that exception type if
> they want to just handle the case wheree getopt throws but don't want to
> swallow other exception types by calling exception and pretty much just want
> to print an error and exit the program or continue without any comand-line
> arguments if that's what they prefer to do.

Isn't that what CommandLineException would be? Or would "getopt" throw other exceptions that would not derive from CommandLineException? So we end up with this:

            GetOptException
               /      \
              /        \
             /          \
CommandLineException  SomeKindOfOtherException

?

> Then you have other exception types derived from GetOptException which deal
> with specific types of issues - such as FlagArgumentMissingException,
> InvalidFlagArgumentException, UnknownFlagException. Each of those exception
> types could then give information which specifically pertains to those errors -
> such as the flag that had a problem, the type that the flag is supposed to
> receive, the type that the flag actually received, the invalid value that the
> flag was given, etc. Such exceptions can then allow you to properly handle and
> report problems with command-line arguments. Right now, all you know is that
> something went wrong, and pretty much the best that you can do is print out
> that something went wrong. You can do any decent error handling at all. You
> need specific exception types which give you the appropriate information in
> order to do that.
>
> Another example is FileException. It would be benificial to have exceptions
> like FileNotFoundException, NotFileException, NotDirException,
> AccessDeniedException, etc which are derived from FileException. Then programs
> could handle the specific instance of what went wrong nice and cleanly rather
> than having to look at error codes. At least FileException provides an error
> code, but that makes for much uglier handling code assuming that you even have
> any clue what the error codes mean. And since the error codes can vary from OS
> to OS, you end up with system-specific error handling code if you try and use
> errno. Whereas if std.file just translated the error code to the correct
> exception type, you're then very cleanly informed as to what the problem was
> and can catch the exception based on which situtations you can recover from
> and which you can't as well as having different catch blocks to handle different
> problems differently.
>
> Simply having an exception type per module is somewhat better than just having
> Exception, because it gives you a better idea of what went wrong (e.g. you got
> a UTFException rather than a FileException), but it's still way too general in
> a lot of cases, and I can see why some would think that it creates needless
> boilerplate code. Also, in some cases, having exception types derive from more
> general exceptions than what the module focuses on can be useful. For
> instance, Java has IOException as the base for all IOExceptions. FileException
> could be derived from that, and then std.stream and std.stdio could could have
> their exception types derive from that as well. Then you could specifically
> handle all exceptions related to I/O together.
>
> I'm completely sold on typed exceptions, but I think that we could do better
> with them than we're currently doing.
>
> - Jonathan M Davis

Otherwise I completely agree.

-- 
/Jacob Carlborg
February 19, 2012
Le 19/02/2012 04:31, Walter Bright a écrit :
> On 2/18/2012 3:13 PM, Andrei Alexandrescu wrote:
>> On 2/18/12 4:26 PM, Jonathan M Davis wrote (abridged):
>> GetOptException
>> FlagArgumentMissingException
>> InvalidFlagArgumentException
>> UnknownFlagException
>> FileException
>> FileNotFoundException
>> NotFileException
>> NotDirException
>> AccessDeniedException
>>
>> I died inside a little.
>
> I think typed exceptions are a good idea, but something looks wrong with
> these.
>
> (Also, having a large number of exception types is going to produce a
> lot of program size bloat. Remember, for EVERY class type, you've got
> the vtbl[], the .init data, and the TypeInfo. Going to town on exception
> types can really add this up.)

Why is the executable size such a big issue ?

Additionnaly, nto providing a convenient Exception hierarchy is going inveitably to lead lib devs to create theire own. And the bloat will be even bigger (due to redundancy) and the result less convenient because the result will be inconsistent for the user of theses libs.
February 19, 2012
How about adding a string[string] or a variant[string] to the Exception class, so one can know details about the subclassed exception without downcasting? How ugly would that be?

For instance:

    ...
    catch (Exception ex) {
      if ("transient" in ex.details) {
            repeatOneMoreTime();
      }
      if ("i18n_code" in ex.details) {
            log(translate(ex.details["i18n_code"]));
      }
    }
    ...

Details can be standard by convention or otherwise custom.
(I can see that this can lead to messy proliferation of details, but at least solves most of the issues).

--jm (BIG FAN OF D. GUYS I LOVE ALL YOUR GOOD WORK)




On Sunday, 19 February 2012 at 08:06:38 UTC, Andrei Alexandrescu wrote:
> On 2/19/12 1:12 AM, Jonathan M Davis wrote:
>> On Sunday, February 19, 2012 00:43:58 Andrei Alexandrescu wrote:
>>> On 2/18/12 8:00 PM, H. S. Teoh wrote:
>>>>>   From this and other posts I'd say we need to design the base exception
>>>>>
>>>>> classes better, for example by defining an overridable property
>>>>> isTransient that tells caller code whether retrying might help.
>>>>
>>>> Just because an exception is transient doesn't mean it makes sense to
>>>> try again. For example, saveFileMenu() might read a filename from the
>>>> user, then save the data to a file. If the user types an invalid
>>>> filename, you will get an InvalidFilename exception. From an abstract
>>>> point of view, an invalid filename is not a transient problem: retrying
>>>> the invalid filename won't make the problem go away. But the application
>>>> in this case *wants* to repeat the operation by asking the user for a
>>>> *different* filename.
>>>>
>>>> On the other hand, if the same exception happens in an app that's trying
>>>> to read a configuration file, then it *shouldn't* retry the operation.
>>>
>>> I'm thinking an error is transient if retrying the operation with the
>>> same exact data may succeed. That's a definition that's simple, useful,
>>> and easy to operate with.
>>
>> A core problem with the idea is that whether or not it makes sense to try
>> again depends on what the caller is doing. In general, I think that it's best
>> to give the caller as much useful information is possible so that _it_ can
>> decide the best way to handle the exception.
>
> That sounds like "I violently agree".
>
> Andrei


February 19, 2012
Le 19/02/2012 09:02, Andrei Alexandrescu a écrit :
> On 2/19/12 12:54 AM, H. S. Teoh wrote:
>> On Sun, Feb 19, 2012 at 12:43:58AM -0600, Andrei Alexandrescu wrote:
>>> On 2/18/12 8:00 PM, H. S. Teoh wrote:
>>>>> From this and other posts I'd say we need to design the base exception
>>>>> classes better, for example by defining an overridable property
>>>>> isTransient that tells caller code whether retrying might help.
>>>>
>>>> Just because an exception is transient doesn't mean it makes sense to
>>>> try again. For example, saveFileMenu() might read a filename from the
>>>> user, then save the data to a file. If the user types an invalid
>>>> filename, you will get an InvalidFilename exception. From an abstract
>>>> point of view, an invalid filename is not a transient problem: retrying
>>>> the invalid filename won't make the problem go away. But the
>>>> application
>>>> in this case *wants* to repeat the operation by asking the user for a
>>>> *different* filename.
>>>>
>>>> On the other hand, if the same exception happens in an app that's
>>>> trying
>>>> to read a configuration file, then it *shouldn't* retry the operation.
>>>
>>> I'm thinking an error is transient if retrying the operation with the
>>> same exact data may succeed. That's a definition that's simple,
>>> useful, and easy to operate with.
>> [...]
>>
>> But if that's the case, what's the use of an exception at all?
>
> Centralization.
>
> Andrei
>

Please stop answering like that. From the begining of this topic Jonathan M Davis, H. S. Teah (and myself ?) raised very valid points. What do you expect from that discussion if yourself you do not put any arguement on the table ?
February 19, 2012
On Sunday, February 19, 2012 12:43:12 Jacob Carlborg wrote:
> On 2012-02-18 23:26, Jonathan M Davis wrote:
> > In the case of getopt, what we want is a GetOptException which is for anything which goes wrong with getopt so that someone can catch that exception type if they want to just handle the case wheree getopt throws but don't want to swallow other exception types by calling exception and pretty much just want to print an error and exit the program or continue without any comand-line arguments if that's what they prefer to do.
> 
> Isn't that what CommandLineException would be? Or would "getopt" throw other exceptions that would not derive from CommandLineException? So we end up with this:
> 
>              GetOptException
>                 /      \
>                /        \
>               /          \
> CommandLineException  SomeKindOfOtherException

IF you want to call it CommandLineException rather than GetOptException, that's fine. I don't much care. The name isn't the critical part here. GetOptException would be more in line with how we've been naming things, but CommandLineException would be more reusable by code outside of std.getopt, so it's probably better. The critical thing here though is that getopt throw an exception (or exceptions) which actually give you the information that you need to handle the problem, which isn't the case right now.

- Jonathan M Davis
February 19, 2012
On Sunday, February 19, 2012 13:20:19 deadalnix wrote:
> Why is the executable size such a big issue ?

Some people complain bitterly about any additional size to the executable at all, whether they use all of the symbols in it or not, and if they don't use all of the symbols, then they're that much more annoyed by the additional size. It crops of semi-frequently around here that someone complains about how big hello world is. Most of the problem goes away if phobos because a shared library like it's going to eventually, but someone is always going to be complaining about binary size - especially with a systems language.

- Jonathan M Davis
February 19, 2012
On 19/02/2012 02:19, Timon Gehr wrote:
> On 02/19/2012 02:23 AM, Jonathan M Davis wrote:
>> One potential issue though is that not all base classes necessarily
>> share the
>> same constructors. Which ones would be grabbed? The ones from the
>> immediate
>> base class? All of them? Only the ones common to all?
>>
>
> There is only one base class. Inheriting constructors from anywhere
> further up the hierarchy cannot work, because then the base class cannot
> be constructed.

To phrase it another way, you could say that the direct base class has already decided which of ITS base class's constructors to wrap and expose. The direct base class's decision is final, so the class extending it further can only base its constructors on that.
February 19, 2012
Le 19/02/2012 02:43, Ben Davis a écrit :
> On 19/02/2012 00:48, Jonathan M Davis wrote:
>> On Saturday, February 18, 2012 16:46:43 H. S. Teoh wrote:
>>> I can't believe something this simple has to be explained so
>>> elaborately. I thought all of us here knew how to use OO??
>>
>> I think that the problem stems from people frequently using exceptions
>> incorrectly, and many of the C++ programmers probably haven't _ever_
>> seen them
>> used correctly, since I don't think that it's very common for C++
>> programs to
>> define exception hierarchies - especially not advanced ones like Java
>> has. And
>> when you see a lot of bad exception code, that tends to turn you off
>> to them,
>> and it definitely doesn't show you how to use them correctly.
>>
>> - Jonathan M Davis
>
> I can assure you they get misused in Java too. Most people write this:
>
> try {
> lots and lots and lots of stuff here
> }
> catch (Exception e) {}
>

You raise 2 prblems of java exception system.

First, RuntimeException is a subclass of Exception. Second, you have to catch all Exceptions except RuntimeException and Error.

We can consider what is good in Java without keeping the bad part.