March 08, 2013
On Friday, March 08, 2013 09:39:12 Rob T wrote:
> That's OK for 20 try catch but specifying catch(Exception E) over and over adds up when you have to write a lot more of those. Copy paste helps, but not always.

So, the only difference is that C++ is

catch(...)
{
    throw trace();
}

whereas D is

catch(Exception e)
{
    throw trace(e);
}

If that's the case, I really don't see what the problem is. It's just a few characters difference.

- Jonathan M Davis
March 08, 2013
On 2013-03-08 08:34, Rob T wrote:
> One more thing, we finally got __FUNCTION__ (and more) added to MASTER
> so that's another missing item that was sorely missed. Now we can easily
> log what functions are catching and throwing exceptions, and more.
>
> The big question is if Throwable will be expanded to automatically
> capture the function signature (as it does with line and file)? I hope
> there are no major concerns over legacy code breakage and it gets added in.

I'm pretty sure there is no concerns. We could just add another overload of the constructor or add an additional default parameter. If a default parameter is added it needs to be added last, which would result some somewhat inconsistent order for the parameters. So I vote for a new overload.

-- 
/Jacob Carlborg
March 08, 2013
On Friday, 8 March 2013 at 09:01:14 UTC, Jonathan M Davis wrote:
> If that's the case, I really don't see what the problem is. It's just a few
> characters difference.

To be honest, the way I look at it, D does this _better_. "throw;" looks like magic and it's accessing global (potentially mutable) state to do something. I haven't done much research into C++'s handling of exceptions (and, in particular, this feature), but I'd be _very_ weary of doing that without knowing whether this global state is thread local or shared. If it's shared, you would have some nice heisenbugs pop up if this was used in multithreaded code.

Using "catch(Exception E) { throw Trace(E); }" is more explicit to what Trace needs to work and, IMO, a better design.
March 08, 2013
On Friday, March 08, 2013 10:07:58 Chris Cain wrote:
> On Friday, 8 March 2013 at 09:01:14 UTC, Jonathan M Davis wrote:
> > If that's the case, I really don't see what the problem is.
> > It's just a few
> > characters difference.
> 
> To be honest, the way I look at it, D does this _better_. "throw;" looks like magic and it's accessing global (potentially mutable) state to do something. I haven't done much research into C++'s handling of exceptions (and, in particular, this feature), but I'd be _very_ weary of doing that without knowing whether this global state is thread local or shared. If it's shared, you would have some nice heisenbugs pop up if this was used in multithreaded code.
> 
> Using "catch(Exception E) { throw Trace(E); }" is more explicit
> to what Trace needs to work and, IMO, a better design.

I agree.

- Jonathan M Davis
March 08, 2013
On Friday, 8 March 2013 at 09:07:59 UTC, Chris Cain wrote:
> On Friday, 8 March 2013 at 09:01:14 UTC, Jonathan M Davis wrote:
>> If that's the case, I really don't see what the problem is. It's just a few
>> characters difference.
>
> To be honest, the way I look at it, D does this _better_. "throw;" looks like magic and it's accessing global (potentially mutable) state to do something. I haven't done much research into C++'s handling of exceptions (and, in particular, this feature), but I'd be _very_ weary of doing that without knowing whether this global state is thread local or shared. If it's shared, you would have some nice heisenbugs pop up if this was used in multithreaded code.
>
> Using "catch(Exception E) { throw Trace(E); }" is more explicit to what Trace needs to work and, IMO, a better design.

The point I'm trying to illustrate is difficult to understand unless you have to personally implement 1000 try/catch statements in your code base. You'll never know how a seemingly trivial item like re-specifying the same pointless catch statement over and over and over again quickly adds up and the frustration knowing that there's a simple solution at hand, but it's not available in what is otherwise a much better language than the one that has the solution.

I'm not at all trying to make a case that D's exception handling is somehow inferior to C++. What tends to happen with D is that it's very close to being "really really good" but it is not yet refined to the same degree that a mature language is, so there are always a few items here and there that could be made to work better. Pointing them out is not an attack on D, it's what is necessary to improve the language.

I suspect it is simple to implement a safe re-throw in D, it's just hard to see why you would want to use it unless you have the experience of making use of try catch very frequently in a large code base.

--rt
March 08, 2013
On 03/08/2013 12:39 AM, Rob T wrote:
> In C++ you can do this
>
> std::exception Trace()
> {
> try
> {
> // key item missing from D
> throw; // <= rethrow last exception

This idiom is know as a Lippincott Function.

Ali

March 08, 2013
On Friday, 8 March 2013 at 09:01:29 UTC, Jacob Carlborg wrote:
> On 2013-03-08 08:34, Rob T wrote:
>> One more thing, we finally got __FUNCTION__ (and more) added to MASTER
>> so that's another missing item that was sorely missed. Now we can easily
>> log what functions are catching and throwing exceptions, and more.
>>
>> The big question is if Throwable will be expanded to automatically
>> capture the function signature (as it does with line and file)? I hope
>> there are no major concerns over legacy code breakage and it gets added in.
>
> I'm pretty sure there is no concerns. We could just add another overload of the constructor or add an additional default parameter. If a default parameter is added it needs to be added last, which would result some somewhat inconsistent order for the parameters. So I vote for a new overload.

Yes that is my choice as well, just add another overload to Throwable and Exception. Exception has the default argument set to __PRETTY_FUNCTION__ which is normally what you'd want to see.

--rt
March 08, 2013
On Friday, March 08, 2013 18:32:43 Rob T wrote:
> The point I'm trying to illustrate is difficult to understand unless you have to personally implement 1000 try/catch statements in your code base. You'll never know how a seemingly trivial item like re-specifying the same pointless catch statement over and over and over again quickly adds up and the frustration knowing that there's a simple solution at hand, but it's not available in what is otherwise a much better language than the one that has the solution.

Except that the C++ one is just as pointless. In both cases, you're telling it to catch everything. It's just that syntax is slightly different, because D doesn't allow you to throw without an explicit variable. And it's only a handful of characters difference in length. So, to some of us at least, it seems like you're blowing things out of proportion. And given the lack of clarity in the C++ solution, it comes off as being worse from a technical perspective, regardless of the typing involved.

- Jonathan M Davis
March 08, 2013
On 3/8/13, Jonathan M Davis <jmdavisProg@gmx.com> wrote:
> In both cases, you're telling it to catch everything.

Also, catch points should be rare, especially the ones which catch base types like Exception or even Error or Throwable. The problem is not the syntax, but the way people use exceptions. Pokemon exception handling is a bad idiom.
March 08, 2013
On Friday, 8 March 2013 at 18:49:53 UTC, Jonathan M Davis wrote:
> Except that the C++ one is just as pointless. In both cases, you're telling it
> to catch everything. It's just that syntax is slightly different, because D
> doesn't allow you to throw without an explicit variable. And it's only a
> handful of characters difference in length. So, to some of us at least, it
> seems like you're blowing things out of proportion. And given the lack of
> clarity in the C++ solution, it comes off as being worse from a technical
> perspective, regardless of the typing involved.
>
> - Jonathan M Davis

I don't wish to blow things out of proportion, and will say again that the main objective I was trying to achieve has been met, thanks to the assistance I received in here, so this remaining item is not all that major, it's just an unnecessary repetitive nuisance to me.

From a technical stand point, I'm implementing a reusable exception handler or dispatcher (I've seen these two terms used to describe it) which is extremely useful to me, and I would assume to many others. There are examples of this concept implemented in C++ by other programmers, that's how I got the idea.

Before I started using an exception handler, my exception handling was very limited and tedious to implement, and I never saw a need to re-throw an exception. There may be other uses for rethrow that I'm not aware of.

What my C++ exception handler does not require, is the exception reference passed in as an argument, so that's one of the main differences between what D allows and what C++ allows. In my case every catch statement and function call will be identical, it's slightly more tedious to type in than the C++ version. No big deal for you, but it is annoying for me because I use this form very frequently.

If you know of a better way to implement an exception handler in D, then I'd like to know about it. For example I do know that D's system allows you to insert callback functions, but I don't yet know how to make use out of it, so  perhaps there's a better way.

Any further help or insight on this matter is appreciated.

--rt