February 21, 2012
On 2/21/12 8:38 AM, foobar wrote:
> On Tuesday, 21 February 2012 at 14:13:55 UTC, Andrei Alexandrescu wrote:
>> On 2/21/12 4:48 AM, foobar wrote:
>>> On Tuesday, 21 February 2012 at 02:23:58 UTC, Andrei Alexandrescu wrote:
>>>> On 2/20/12 7:02 PM, Juan Manuel Cabo wrote:
>>>>> oops, sorry!! I just saw a post by someone named Jose. My thousand
>>>>> apollogies!!
>>>>
>>>> I got confused. It was your argument I meant to refer to - adding info
>>>> to the exception in flight.
>>>>
>>>> Andrei
>>>
>>> I'd implement this along these lines:
>>>
>>> class WithErrorCode(E) : E {
>>> int errorCode;
>>> this(Args)(int err, Args args) { this.errorCode = err; super(args); }
>>> }
>>>
>>> and add this wrapper where relevant. e.g. replace:
>>> throw new FileNotFoundException(...);
>>> with something like:
>>> throw new WithErrorCode!FileNotFoundException(-1, ...);
>>>
>>> This is a localized change that doesn't affect all uses of exceptions
>>> and it remains type-safe. surely this is a better solution than the hash
>>> table?
>>
>> The two approaches don't compete as one is static and the other is
>> dynamic. For example, how does one add contextual information "While
>> opening table in {database}" to the current exception of type
>> WithErrorCode!FileNotFoundException?
>>
>>
>> Andrei
>
> This works:
> // note: the int parameter above isn't static
> dbConn.query("select age from people where id='foobar'");
> throw new WithErrorCode!FileNotFoundException(
> db.rs.getValue(1), "file not found");

I don't understand this example.

> This approach fails if you don't know ahead of time what *fields* you
> want to add to your exception but I'd argue that this is unrealistic. An
> exception is thrown as a response to a specific erroneous condition
> which means you already know *what* the problem is and what kind of data
> is needed to describe it.
>
> Can you offer a real world use-case where the above isn't sufficient?

This has been discussed. A function would want to add contextual information to an exception and rethrow it. Requiring a new type for each such flow does not scale.


Andrei
February 21, 2012
On Tuesday, 21 February 2012 at 02:33:15 UTC, Robert Jacques wrote:
> Nope. See (https://jshare.johnshopkins.edu/rjacque2/public_html/ )


Any luck in getting the required patches into phobos?

I'd love to see this full thing in there for the next release.

It rox.

February 21, 2012
> This works:
> // note: the int parameter above isn't static
> dbConn.query("select age from people where id='foobar'");
> throw new WithErrorCode!FileNotFoundException(
>           db.rs.getValue(1), "file not found");
...
> Can you offer a real world use-case where the above isn't sufficient?


What happened is that a file wasn't found. What one wants to catch is a FileNotFoundException.

Do you suggest that I have to:

   try {
       ...
   } catch (FileNotFoundException ex) {
       ...
   } catch (WithErrorCode!FileNotFoundException ex) {
       ...
   } catch (WithRainbows!FileNotFoundException ex) {
       ...
   }
and so on?

--jm


February 21, 2012
Le 21/02/2012 11:55, deadalnix a écrit :
> First great post. Don't be sorry, it is insightful. The Condition catgory make a lot of sense to me.
>
> Le 21/02/2012 09:15, H. S. Teoh a écrit :
>> Currently, I'm still unsure whether Conditions and Exceptions should be unified, or they should be kept separate; deadalnix recommended they be kept separate, but I'd like to open it for discussion.
>>
>
> I think we could reconciliate the 2 worlds. Condition may provide @property Exception exception() so you can get the Exception. Eventually, the Condition can return itself so it is the Exception.
>
> This Exception can be used by the handler to get information about the problem more specifically (if required). The Exception can also be used to throw it, if no handler is provided, or if the handler decide it is the right thing to do.
>
> I suggested this mecanism should be implemented into std.condition and still think this is the way to go. Addition to the language itself should be as limited as possible (ie only occur if the compiler can take advantage of this, for example to optimize, or if this isn't implementable using the current state of the language).
>
> This mecanism is not intended to replace Exception, but to provide a more convenient, higher level (and probably more performant) than the Exception mecanism. We fail back to Exceptions if this mecanism fail.

I come up with a sample code with the transient case. What do you think ?


February 21, 2012
On 2012-02-21 15:16, Andrei Alexandrescu wrote:
> On 2/21/12 5:11 AM, Jacob Carlborg wrote:
>> On 2012-02-21 03:34, Andrei Alexandrescu wrote:
>> I think the correct way of handling this is provide enough information
>> in the exception so a message can be built where the exception is
>> caught.
>
> Quite so. I'd add "using a unified interface so reusable code can work
> with heterogeneous concrete exceptions".
>
>> It might happen the you want to catch the same exception in
>> different parts of the code and build different messages.
>
> Yah, that's different string tables.

So you would set the string table where the exception is caught?

-- 
/Jacob Carlborg
February 21, 2012
> I think he meant to say things have been like that for a while and there's no blood in the streets.

That's exactly what I meant.

And even if one makes those fields private, anyone can take a pointer
to the class or void[] or whatever and do a mess. (Java isn't exepmpt,
you can do a mess with reflection there).
So there is a minimum of trust that we put on APIs and code that
we call downstream. The same trust that one puts, to begin with,
when one expects that an exception will be thrown when an error happens.

Ruby and PHP are based on a lot of trust for instance!
Having the advantages of staticlly typed language doesn't mean
that one must turn the advantages into disadvantages and start
hammering screws because we love hammers.

--jm


On 02/21/2012 11:20 AM, Andrei Alexandrescu wrote:
> On 2/21/12 6:36 AM, Jacob Carlborg wrote:
>> On 2012-02-20 23:44, Juan Manuel Cabo wrote:
>>>> I still don't like the idea of using Variant[string], though.
>>>>
>>>> (1) It doesn't allow compile-time type checking. This is a big minus, in
>>>> my book.
>>>
>>> When you need compile-time type checking, define a variable in your
>>> class.
>>> Just make sure that you are creating that new exception class for a
>>> good reason.
>>>
>>> When a user needs to add a variable to the exception, he can add it without putting your exception class chained in a new type of exception, that will hide your class from being selected by upstream catch blocks in the call tree.
>>>
>>>>
>>>> (2) It's overly flexible. Anyone along the call stack can insert
>>>> (hopefully NOT delete!!) additional data into the Exception object, as
>>>> the stack is unwound.
>>>
>>> As is currently the case.
>>> Did you know that anyone can overwrite any field of the exception and
>>> rethrow it? Such as msg field and so on?
>>
>> No one says the fields need to be public instance variables. You could take the arguments in the constructor and only have getters.
> 
> I think he meant to say things have been like that for a while and there's no blood in the streets.
> 
> Andrei
> 
> 

February 21, 2012
Never mind modifying fields of the exception at some intermediate catch place.
Someone could even catch the exception and not rethrow it.
So: do some trusting. Life gets easier :-)

--jm


On 02/21/2012 12:46 PM, Juan Manuel Cabo wrote:
>> I think he meant to say things have been like that for a while and there's no blood in the streets.
> 
> That's exactly what I meant.
> 


February 21, 2012
On Tuesday, 21 February 2012 at 15:38:15 UTC, Juan Manuel Cabo wrote:
>> This works:
>> // note: the int parameter above isn't static
>> dbConn.query("select age from people where id='foobar'");
>> throw new WithErrorCode!FileNotFoundException(
>>           db.rs.getValue(1), "file not found");
> ...
>> Can you offer a real world use-case where the above isn't sufficient?
>
>
> What happened is that a file wasn't found. What one wants to catch is
> a FileNotFoundException.
>
> Do you suggest that I have to:
>
>    try {
>        ...
>    } catch (FileNotFoundException ex) {
>        ...
>    } catch (WithErrorCode!FileNotFoundException ex) {
>        ...
>    } catch (WithRainbows!FileNotFoundException ex) {
>        ...
>    }
> and so on?
>
> --jm

FileNotFoundException is the super class of the others so the first catch clause is enough. in fact, the others will never be called if listed in the above order.
February 21, 2012
> FileNotFoundException is the super class of the others so the first catch clause is enough. in fact, the others will never be called if listed in the above order.

Nice! I missed that. But what if you want to add ErrorCode and Rainbows? And with your approach, one has to test for type and downcast, or otherwise have multiple catch blocks (I don't want to miss plain FileNotFoundExceptions). So it's square one.

With Variant[string] (or something equivalent, nothing better comes to mind)
one does:


    try {
        ...
    } catch (FileNotFoundException ex) {
         if (ex.hasInfo(MyNameConstant)) {
             ... use that ...
         }
         ... common handling ...
    }


--jm


February 21, 2012
Also, you would lose the stacktrace by rethrowing with a different exception object. (Currently, the stacktrace is lost by rethrowing the same object, but the Exception.file and Exception.line are not lost, and it seems that it is very easy to not lose the stacktrace when rethrowing, and it is the correct thing (for instance, java doesn't lose the stacktrace when rethrowing, and C++ with its throw; statement for rethrowing doesn't either).

--jm

On 02/21/2012 01:15 PM, Juan Manuel Cabo wrote:
>> FileNotFoundException is the super class of the others so the first catch clause is enough. in fact, the others will never be called if listed in the above order.
> 
> Nice! I missed that. But what if you want to add ErrorCode and Rainbows? And with your approach, one has to test for type and downcast, or otherwise have multiple catch blocks (I don't want to miss plain FileNotFoundExceptions). So it's square one.
> 
> With Variant[string] (or something equivalent, nothing better comes to mind)
> one does:
> 
> 
>     try {
>         ...
>     } catch (FileNotFoundException ex) {
>          if (ex.hasInfo(MyNameConstant)) {
>              ... use that ...
>          }
>          ... common handling ...
>     }
> 
> 
> --jm
> 
>