www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Trailing catch on function?

reply Manu via Digitalmars-d <digitalmars-d puremagic.com> writes:
Hey people, I'm passing lots of D function pointers to C, and naturally,
the C api expects the fp signatures are all nothrow.

Which means, my D functions all look like this:

void callback() nothrow
{
try
{
...lots of code...
}
catch (Exception e)
{
...log error or abort...
}
}


I'm generally annoyed by all the extra indentation.
Since nothrow is a central thing in D, I wondered if it would be reasonable
to allow a nice little bit of sugar to assist working with nothrow that
would look like this:

void catchingCallback() nothrow
{
...lots of code...
}
catch (Exception e)
{
...log error or abort...
}

Syntactically similar to the existing in/out sections, although I think it
would be nicer at the bottom...
It's simply a lowering which wraps the entire function body scope in a try.

It's not a really big deal, but it would feel a whole lot tidier in my
existing code.
I don't imagine how it would really affect anything else.

Terrible idea?
Nov 06 2016
next sibling parent Jacob Carlborg <doob me.com> writes:
On 2016-11-07 05:30, Manu via Digitalmars-d wrote:
 Hey people, I'm passing lots of D function pointers to C, and naturally,
 the C api expects the fp signatures are all nothrow.

 Which means, my D functions all look like this:

 void callback() nothrow
 {
 try
 {
 ...lots of code...
 }
 catch (Exception e)
 {
 ...log error or abort...
 }
 }


 I'm generally annoyed by all the extra indentation.
 Since nothrow is a central thing in D, I wondered if it would be
 reasonable to allow a nice little bit of sugar to assist working with
 nothrow that would look like this:

 void catchingCallback() nothrow
 {
 ...lots of code...
 }
 catch (Exception e)
 {
 ...log error or abort...
 }

 Syntactically similar to the existing in/out sections, although I think
 it would be nicer at the bottom...
 It's simply a lowering which wraps the entire function body scope in a try.

 It's not a really big deal, but it would feel a whole lot tidier in my
 existing code.
 I don't imagine how it would really affect anything else.

 Terrible idea?
No, I like it. Ruby supports this feature. But I think I would prefer the catch inside the body. That works nicely when not curly braces are required. BTW, this has been proposed before, but I cannot find it in the newsgroup. -- /Jacob Carlborg
Nov 07 2016
prev sibling next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 11/6/2016 8:30 PM, Manu via Digitalmars-d wrote:
 Hey people, I'm passing lots of D function pointers to C, and naturally, the C
 api expects the fp signatures are all nothrow.

 Which means, my D functions all look like this:

 void callback() nothrow
 {
 try
 {
 ...lots of code...
 }
 catch (Exception e)
 {
 ...log error or abort...
 }
 }


 I'm generally annoyed by all the extra indentation.
void callback() nothrow { scope (failure) { ...log error or abort... } ...lots of code... }
Nov 07 2016
next sibling parent reply Robert burner Schadek <rburners gmail.com> writes:
On Monday, 7 November 2016 at 23:37:18 UTC, Walter Bright wrote:
 void callback() nothrow
 {
     scope (failure)
     {
         ...log error or abort...
     }
     ...lots of code...
 }
Who to get the Exception thrown in the scope(failure)
Nov 07 2016
next sibling parent Robert burner Schadek <rburners gmail.com> writes:
On Tuesday, 8 November 2016 at 00:12:09 UTC, Robert burner 
Schadek wrote:

 Who to get the Exception thrown in the scope(failure)
Who to --> How do you ...
Nov 07 2016
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 11/7/2016 4:12 PM, Robert burner Schadek wrote:
 On Monday, 7 November 2016 at 23:37:18 UTC, Walter Bright wrote:
 void callback() nothrow
 {
     scope (failure)
     {
         ...log error or abort...
     }
     ...lots of code...
 }
Who to get the Exception thrown in the scope(failure)
You don't. The exception is also rethrown, so it isn't an exact replacement. (The 'nothrow' is a mistake on my part.)
Nov 07 2016
next sibling parent reply Mike Parker <aldacron gmail.com> writes:
On Tuesday, 8 November 2016 at 01:50:26 UTC, Walter Bright wrote:
 On 11/7/2016 4:12 PM, Robert burner Schadek wrote:
 On Monday, 7 November 2016 at 23:37:18 UTC, Walter Bright 
 wrote:
 void callback() nothrow
 {
     scope (failure)
     {
         ...log error or abort...
     }
     ...lots of code...
 }
Who to get the Exception thrown in the scope(failure)
You don't. The exception is also rethrown, so it isn't an exact replacement. (The 'nothrow' is a mistake on my part.)
In this specific case, a function used as a callback for a C API, it really ought to be nothrow because of the inconsistent behavior with propagating exceptions across language boundaries. scope(exit) just isn't useful here. I recall a proposal somewhere for something like scope(exit, e), where 'e' is a Throwable instance. That would be great for logging the exception message, but unless it also allowed for aborting the throw, it still wouldn't be useful in this specific case.
Nov 07 2016
parent Manu via Digitalmars-d <digitalmars-d puremagic.com> writes:
On 8 November 2016 at 12:50, Mike Parker via Digitalmars-d <
digitalmars-d puremagic.com> wrote:

 On Tuesday, 8 November 2016 at 01:50:26 UTC, Walter Bright wrote:

 On 11/7/2016 4:12 PM, Robert burner Schadek wrote:

 On Monday, 7 November 2016 at 23:37:18 UTC, Walter Bright wrote:

 void callback() nothrow
 {
     scope (failure)
     {
         ...log error or abort...
     }
     ...lots of code...
 }
Who to get the Exception thrown in the scope(failure)
You don't. The exception is also rethrown, so it isn't an exact replacement. (The 'nothrow' is a mistake on my part.)
In this specific case, a function used as a callback for a C API, it really ought to be nothrow because of the inconsistent behavior with propagating exceptions across language boundaries. scope(exit) just isn't useful here.
It's not strictly useful for interaction with C, it would be equally useful in the situation where a nothrow function returns an error code or something. The tail-catch block could do the translation and return the error, and it would be in a nice place separate from the main function body.
Nov 08 2016
prev sibling next sibling parent Robert burner Schadek <rburners gmail.com> writes:
On Tuesday, 8 November 2016 at 01:50:26 UTC, Walter Bright wrote:
 You don't. The exception is also rethrown, so it isn't an exact 
 replacement. (The 'nothrow' is a mistake on my part.)
this: scope(failure, Exception e) { // Do something with e } would be nice
Nov 08 2016
prev sibling parent reply Anonymouse <asdf asdf.net> writes:
On Tuesday, 8 November 2016 at 01:50:26 UTC, Walter Bright wrote:
 Who to get the Exception thrown in the scope(failure)
You don't. The exception is also rethrown, so it isn't an exact replacement. (The 'nothrow' is a mistake on my part.)
You can eat the exception by returning in the scope guard. Since it seems to trigger on Throwables it also eats Errors, sadly. void fun() nothrow { scope(failure) { // cleanup logic return; } throw new Exception("I don't get rethrown"); }
Nov 08 2016
parent Daniel N <no public.email> writes:
On Tuesday, 8 November 2016 at 11:24:59 UTC, Anonymouse wrote:
 You can eat the exception by returning in the scope guard. 
 Since it seems to trigger on Throwables it also eats Errors, 
 sadly.
Interesting! Considering this works: scope(failure) { abort(); return; } I had expected this to work also: scope(failure) abort(); But I guess D lacks support for noreturn attribute on abort?
Nov 08 2016
prev sibling parent reply Manu via Digitalmars-d <digitalmars-d puremagic.com> writes:
On 8 November 2016 at 09:37, Walter Bright via Digitalmars-d <
digitalmars-d puremagic.com> wrote:

 On 11/6/2016 8:30 PM, Manu via Digitalmars-d wrote:

 Hey people, I'm passing lots of D function pointers to C, and naturally,
 the C
 api expects the fp signatures are all nothrow.

 Which means, my D functions all look like this:

 void callback() nothrow
 {
 try
 {
 ...lots of code...
 }
 catch (Exception e)
 {
 ...log error or abort...
 }
 }


 I'm generally annoyed by all the extra indentation.
void callback() nothrow { scope (failure) { ...log error or abort... } ...lots of code... }
scope(failure) doesn't catch... how is that function nothrow?
Nov 08 2016
parent reply Daniel N <no public.email> writes:
On Tuesday, 8 November 2016 at 16:02:25 UTC, Manu wrote:
 scope(failure) doesn't catch... how is that function nothrow?
Seems like you overlooked Anonymouse's comment? scope(failure) catches just fine. scope(failure) return -1; throw new Exception("failure"); return 0; This will return -1, with no need for extra indentation.
Nov 09 2016
parent reply Anonymouse <asdf asdf.net> writes:
On Wednesday, 9 November 2016 at 09:49:08 UTC, Daniel N wrote:
 On Tuesday, 8 November 2016 at 16:02:25 UTC, Manu wrote:
 scope(failure) doesn't catch... how is that function nothrow?
Seems like you overlooked Anonymouse's comment? scope(failure) catches just fine. scope(failure) return -1; throw new Exception("failure"); return 0; This will return -1, with no need for extra indentation.
I understand its convenience, but as long as it also catches Errors I'm not sure this is something you want to do though. You won't be able to differentiate between invalid input and bugs in the code, potentially continuing in an invalid state. Subsetting failure into a scope(exception) would work, but I'm not sure how the interplay between them would work. Or are Errors so fatal that it should always immediately crash the program, ignored by scope(failure)?
Nov 12 2016
parent =?UTF-8?B?QW5kcsOp?= Puel <andrepuel gmail.com> writes:
On Saturday, 12 November 2016 at 12:17:35 UTC, Anonymouse wrote:
 On Wednesday, 9 November 2016 at 09:49:08 UTC, Daniel N wrote:
 On Tuesday, 8 November 2016 at 16:02:25 UTC, Manu wrote:
 scope(failure) doesn't catch... how is that function nothrow?
Seems like you overlooked Anonymouse's comment? scope(failure) catches just fine. scope(failure) return -1; throw new Exception("failure"); return 0; This will return -1, with no need for extra indentation.
I understand its convenience, but as long as it also catches Errors I'm not sure this is something you want to do though. You won't be able to differentiate between invalid input and bugs in the code, potentially continuing in an invalid state. Subsetting failure into a scope(exception) would work, but I'm not sure how the interplay between them would work. Or are Errors so fatal that it should always immediately crash the program, ignored by scope(failure)?
That is how I do it: auto csafe(alias f)() nothrow { try { return f(); } catch(Throwable e) { import core.stdc.stdlib : abort; import std.stdio : stderr; stderr.writeln("Fatal error."); stderr.writeln(e); abort(); assert(false); } } And then: extern (C) int yada() nothrow { return csafe!(() { return maythrowFunction(); }); } You might extend the `csafe` function to do some kind of error handling, or invoking error callback instead of just aborting the execution.
Nov 13 2016
prev sibling parent Steven Schveighoffer <schveiguy yahoo.com> writes:
On 11/6/16 11:30 PM, Manu via Digitalmars-d wrote:
 Hey people, I'm passing lots of D function pointers to C, and naturally,
 the C api expects the fp signatures are all nothrow.

 Which means, my D functions all look like this:

 void callback() nothrow
 {
 try
 {
 ...lots of code...
 }
 catch (Exception e)
 {
 ...log error or abort...
 }
 }


 I'm generally annoyed by all the extra indentation.
 Since nothrow is a central thing in D, I wondered if it would be
 reasonable to allow a nice little bit of sugar to assist working with
 nothrow that would look like this:

 void catchingCallback() nothrow
 {
 ...lots of code...
 }
 catch (Exception e)
 {
 ...log error or abort...
 }

 Syntactically similar to the existing in/out sections, although I think
 it would be nicer at the bottom...
 It's simply a lowering which wraps the entire function body scope in a try.
the tough thing about this is, what is in scope inside the catch? You are outside the function, so the only thing available is the exception. Being stupid, I thought maybe this might work: nothrow void catchingCallback() try { } catch(Exception e) { } Thinking "hey, a function body is like a scope, maybe I can just do one statement instead!" But it doesn't work. However, this isn't far off: void catchingCallBack() nothrow {try { } catch(Exception e) { }} Another solution may be to write your function as normal, and then mixin definitions for a nothrow version of it. Of course, this means you have to handle all your exceptions the same way. -Steve
Nov 07 2016