www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - scope guards

reply Manu via Digitalmars-d <digitalmars-d puremagic.com> writes:
I'm trying to make better use of scope guards, but I find myself belting
out try/catch statements almost everywhere.
I'm rather disappointed, because scope guards are advertised to offer the
promise of eliminating try/catch junk throughout your code, and I'm just
not finding that to be the practical reality.

I think the core of the problem is that scope(failure) is indiscriminate,
but I want to filter it for particular exceptions. The other issue is that
you still need a catch() if you don't actually want the program to
terminate, which implies a try... :/

One thing that may be leveraged to eliminate most catch blocks is the
existing ability to return from scope guard blocks, allowing to gracefully
return from a function while unwinding, akin to a catch.
The problem then is that you can't handle specific exceptions.

I'm thinking this would make all the difference:

scope(failure, MyException e) // only executed for exceptions of type
MyException
{
  writeln(e.msg); // can refer to the exception in this failure block
  return failureValue; // and can gracefully return from the function too
}

That would eliminate about 80% of my try/catch blocks.
The remaining suffer from the problem where I want to respond to exceptions
NOT of a specific type, ie, clean up in the case of an unexpected/unknown
exception.

scope(failure, ~MyException)
{
  // clean up, because some unexpected exception occurred that I
don't/can't handle.
}


Is there already some mechanism to do this? I couldn't find anything in the
docs.
It seems like an obvious thing to want to do.
Aug 03 2014
next sibling parent reply Mike Parker <aldacron gmail.com> writes:
On 8/4/2014 12:28 AM, Manu via Digitalmars-d wrote:
 I'm trying to make better use of scope guards, but I find myself belting
 out try/catch statements almost everywhere.
 I'm rather disappointed, because scope guards are advertised to offer
 the promise of eliminating try/catch junk throughout your code, and I'm
 just not finding that to be the practical reality.

 I think the core of the problem is that scope(failure) is
 indiscriminate, but I want to filter it for particular exceptions. The
 other issue is that you still need a catch() if you don't actually want
 the program to terminate, which implies a try... :/
Scope guards are for when you don't need to handle exceptions. If you need the exceptions, use try...catch. I don't think it would be a good idea to have two different means of handling exceptions. --- This email is free from viruses and malware because avast! Antivirus protection is active. http://www.avast.com
Aug 03 2014
parent reply Manu via Digitalmars-d <digitalmars-d puremagic.com> writes:
On 4 August 2014 12:04, Mike Parker via Digitalmars-d <
digitalmars-d puremagic.com> wrote:

 On 8/4/2014 12:28 AM, Manu via Digitalmars-d wrote:

 I'm trying to make better use of scope guards, but I find myself belting
 out try/catch statements almost everywhere.
 I'm rather disappointed, because scope guards are advertised to offer
 the promise of eliminating try/catch junk throughout your code, and I'm
 just not finding that to be the practical reality.

 I think the core of the problem is that scope(failure) is
 indiscriminate, but I want to filter it for particular exceptions. The
 other issue is that you still need a catch() if you don't actually want
 the program to terminate, which implies a try... :/
Scope guards are for when you don't need to handle exceptions. If you need the exceptions, use try...catch. I don't think it would be a good idea to have two different means of handling exceptions.
Well, then they're not particularly useful in practise. I'm finding that I can rarely blanket an operation across all exceptions. The nature of exceptions is that they are of a particular type, so why have no access to that concept when trying to respond to them...
Aug 03 2014
parent reply "Dicebot" <public dicebot.lv> writes:
On Monday, 4 August 2014 at 03:15:32 UTC, Manu via Digitalmars-d 
wrote:
 Well, then they're not particularly useful in practise. I'm 
 finding that I
 can rarely blanket an operation across all exceptions.
 The nature of exceptions is that they are of a particular type, 
 so why have
 no access to that concept when trying to respond to them...
You may have coding style particularly alien to scope guards :) Those are very convenient to use as a simple an generic alternative to RAII, especially when interfacing with C libraries. I find that most often one wants to catch majority of exceptions only in somewhat high level parts of code (i.e. main loop) and rest is just cleanup code - perfect fit for scope guards. scope(success) is probably one I don't see use case case for though
Aug 03 2014
parent reply Manu via Digitalmars-d <digitalmars-d puremagic.com> writes:
On 4 August 2014 13:44, Dicebot via Digitalmars-d <
digitalmars-d puremagic.com> wrote:

 On Monday, 4 August 2014 at 03:15:32 UTC, Manu via Digitalmars-d wrote:

 Well, then they're not particularly useful in practise. I'm finding that I
 can rarely blanket an operation across all exceptions.
 The nature of exceptions is that they are of a particular type, so why
 have
 no access to that concept when trying to respond to them...
You may have coding style particularly alien to scope guards :) Those are very convenient to use as a simple an generic alternative to RAII, especially when interfacing with C libraries.
Sure, scope() may be useful for this, but it seems in my experience that destructors almost always perform this without any additional code at the callsite. C libraries are exactly the only case where I've managed to use scope() successfully. This seems like a waste. A key talking point of the language finds use almost exclusively when used in conjunction with another language... :/ I find that most often one wants to catch majority of exceptions only in
 somewhat high level parts of code (i.e. main loop) and rest is just cleanup
 code - perfect fit for scope guards.
I can't think of many instances where I would want to catch an exception at the main loop unless it was completely unexpected, like out of memory or something. Almost all exceptions I throw are in relation to bad input data, and they are to be caught at a slightly higher level of input processing. My code has become try/catch-tastic, and I really don't like looking at it. It rather sickens me and reminds me of Java, and I'm strongly tempted to just abandon my experiment and return to C-style error handling with sentinel values. So... why not make scope guards more useful? It wouldn't be hard. scope(failure, MyException e) is completely non-destructive, and adds significant power to the concept. scope(success) is probably one I don't see use case case for though

Yeah, I can't imagine a use for it either.
Aug 03 2014
next sibling parent reply "Jacob Carlborg" <doob me.com> writes:
On Monday, 4 August 2014 at 04:09:07 UTC, Manu via Digitalmars-d 
wrote:

 Almost all exceptions I throw are in relation to bad input 
 data, and they
 are to be caught at a slightly higher level of input 
 processing. My code
 has become try/catch-tastic, and I really don't like looking at 
 it.
Why does it matter it has a lot of try/catch-blocks.
 It rather sickens me and reminds me of Java
So just because your code looks like Java you want to come up with a new feature that is exactly like "catch", but with a new name. Instead your code will become scope-tastic (whatever that means) and it doesn't look like Java because it use a different keyword.
 , and I'm strongly tempted to just
 abandon my experiment and return to C-style error handling with 
 sentinel
 values.
I can't see how that will improve anything. Seems like you have some grudge against Java and don't won't your code to look like it.
 So... why not make scope guards more useful? It wouldn't be 
 hard.
 scope(failure, MyException e) is completely non-destructive, 
 and adds
 significant power to the concept.
I think it's better to support catch-blocks without a try-block. BTW, if I recall correctly, I have already proposed this and it was turned down.
 Yeah, I can't imagine a use for it either.
Logging perhaps.
Aug 04 2014
next sibling parent reply "Daniel Murphy" <yebbliesnospam gmail.com> writes:
"Jacob Carlborg"  wrote in message 
news:olhenmuccsbpcjbpaiqz forum.dlang.org...

 I can't see how that will improve anything. Seems like you have some 
 grudge against Java and don't won't your code to look like it.
But really, doesn't everyone?
Aug 04 2014
parent Jacob Carlborg <doob me.com> writes:
On 2014-08-04 11:07, Daniel Murphy wrote:

 But really, doesn't everyone?
Sure, but not to the point where I would go back to C style error handling. -- /Jacob Carlborg
Aug 05 2014
prev sibling parent reply Manu via Digitalmars-d <digitalmars-d puremagic.com> writes:
On 4 August 2014 17:21, Jacob Carlborg via Digitalmars-d <
digitalmars-d puremagic.com> wrote:

 On Monday, 4 August 2014 at 04:09:07 UTC, Manu via Digitalmars-d wrote:

  Almost all exceptions I throw are in relation to bad input data, and they
 are to be caught at a slightly higher level of input processing. My code
 has become try/catch-tastic, and I really don't like looking at it.
Why does it matter it has a lot of try/catch-blocks.
I hate pointless brace and indentation spam, I feel it severely damages the readability of my code. And try/catch has a natural tendency to produce horrid nested structures. I would rather C-style error reporting via sentinel values and 'if()' than try/catch in practically every case imaginable, especially when try/catches start to nest themselves. It rather sickens me and reminds me of Java

 So just because your code looks like Java you want to come up with a new
 feature that is exactly like "catch", but with a new name. Instead your
 code will become scope-tastic (whatever that means) and it doesn't look
 like Java because it use a different keyword.
Okay, so why are scope guards such a key talking point in D if people loved try/catch? 'scope-tastic' code would be flat and sequential. I find flat and sequential code MUCH easier to reason about. Again, why would anyone care about 'scope' if they didn't feel this way at some level? , and I'm strongly tempted to just
 abandon my experiment and return to C-style error handling with sentinel
 values.
I can't see how that will improve anything. Seems like you have some grudge against Java and don't won't your code to look like it.
It will produce flat sequential code which is easier to follow. So... why not make scope guards more useful? It wouldn't be hard.
 scope(failure, MyException e) is completely non-destructive, and adds
 significant power to the concept.
I think it's better to support catch-blocks without a try-block. BTW, if I recall correctly, I have already proposed this and it was turned down.
I agree, I had the same thought. But I felt it was better to integrate it into an existing (and popular) structure than to form a new one. I actually think there would be a valuable place for both though.
Aug 04 2014
parent Jacob Carlborg <doob me.com> writes:
On 2014-08-04 12:09, Manu via Digitalmars-d wrote:

 I hate pointless brace and indentation spam, I feel it severely damages
 the readability of my code. And try/catch has a natural tendency to
 produce horrid nested structures.
 I would rather C-style error reporting via sentinel values and 'if()'
 than try/catch in practically every case imaginable, especially when
 try/catches start to nest themselves.
If you want to the if-statements to have the same semantics won't those be nested as well. BTW, why don't you just wrap the whole function in a try-block and add several catch blocks to it. No need to nest them, it will also be closer to how scope-statements behave.
 Okay, so why are scope guards such a key talking point in D if people
 loved try/catch?
 'scope-tastic' code would be flat and sequential. I find flat and
 sequential code MUCH easier to reason about. Again, why would anyone
 care about 'scope' if they didn't feel this way at some level?
You need to nest the scope-statements to have the same semantics as nested try-catch. Or don't nest the try-catch, see above.
         , and I'm strongly tempted to just
         abandon my experiment and return to C-style error handling with
         sentinel
         values.


     I can't see how that will improve anything. Seems like you have some
     grudge against Java and don't won't your code to look like it.


 It will produce flat sequential code which is easier to follow.
You can do that with try-catch as well, see above.
 I agree, I had the same thought. But I felt it was better to integrate
 it into an existing (and popular) structure than to form a new one.
 I actually think there would be a valuable place for both though.
So you think a "catch" with an implicit "try" is a completely new feature? -- /Jacob Carlborg
Aug 05 2014
prev sibling next sibling parent reply "Dicebot" <public dicebot.lv> writes:
On Monday, 4 August 2014 at 04:09:07 UTC, Manu via Digitalmars-d 
wrote:
 Sure, scope() may be useful for this, but it seems in my 
 experience that
 destructors almost always perform this without any additional 
 code at the
 callsite.
Destructors only work if: a) you already have RAII wrappers provided, otherwise it is much more code to write b) you work with structs, class destruction is non-determenistic
Aug 04 2014
parent reply "Atila Neves" <atila.neves gmail.com> writes:
On Monday, 4 August 2014 at 14:57:44 UTC, Dicebot wrote:
 On Monday, 4 August 2014 at 04:09:07 UTC, Manu via 
 Digitalmars-d wrote:
 Sure, scope() may be useful for this, but it seems in my 
 experience that
 destructors almost always perform this without any additional 
 code at the
 callsite.
Destructors only work if: a) you already have RAII wrappers provided, otherwise it is much more code to write b) you work with structs, class destruction is non-determenistic
b) And even then, struct destruction can be non-deterministic if they happen to be in a dynamic array...
Aug 05 2014
parent reply Manu via Digitalmars-d <digitalmars-d puremagic.com> writes:
On 5 August 2014 19:37, Atila Neves via Digitalmars-d <
digitalmars-d puremagic.com> wrote:

 On Monday, 4 August 2014 at 14:57:44 UTC, Dicebot wrote:

 On Monday, 4 August 2014 at 04:09:07 UTC, Manu via Digitalmars-d wrote:

 Sure, scope() may be useful for this, but it seems in my experience that
 destructors almost always perform this without any additional code at the
 callsite.
Destructors only work if: a) you already have RAII wrappers provided, otherwise it is much more code to write b) you work with structs, class destruction is non-determenistic
b) And even then, struct destruction can be non-deterministic if they happen to be in a dynamic array...
'scope' class destruction is deterministic though right? http://dlang.org/statement.html : there are examples of stuff like this: scope Foo f = new Foo();
Aug 05 2014
next sibling parent reply "Dicebot" <public dicebot.lv> writes:
On Tuesday, 5 August 2014 at 10:39:01 UTC, Manu via Digitalmars-d 
wrote:
 'scope' class destruction is deterministic though right?

 http://dlang.org/statement.html : there are examples of stuff 
 like this:

 scope Foo f = new Foo();
scope classes are not supported anymore and considered D1 legacy ;) Though not officially deprecated I doubt anyone actually pays attention if those are even working. Official replacement is http://dlang.org/phobos/std_typecons.html#.scoped Many of dlang.org documentation pages that are not generated from actual code are outdated in that regard.
Aug 05 2014
parent "Daniel Murphy" <yebbliesnospam gmail.com> writes:
"Dicebot"  wrote in message news:drbpycdjoakiofwnzmkt forum.dlang.org...

 scope classes are not supported anymore and considered D1 legacy ;) Though 
 not officially deprecated I doubt anyone actually pays attention if those 
 are even working.
I do, for DDMD. The only thing wrong with them is that they're not safe, and hopefully we'll be fixing it so 'scope' actually works at some point...
Aug 05 2014
prev sibling parent Jacob Carlborg <doob me.com> writes:
On 2014-08-05 12:38, Manu via Digitalmars-d wrote:

 'scope' class destruction is deterministic though right?

 http://dlang.org/statement.html : there are examples of stuff like this:

 scope  Foo f =new  Foo();
Yes, but you don't know in the destructor of "Foo" if it was used in a scope declaration like above or not, unless you declare the whole class as "scope". BTW, Tango in D1 solved this by introducing Object.dispose which was called then "scope" or "delete" was used. -- /Jacob Carlborg
Aug 05 2014
prev sibling parent "Sebastiaan Koppe" <mail skoppe.eu> writes:
On Monday, 4 August 2014 at 04:09:07 UTC, Manu via Digitalmars-d 
wrote:
 Almost all exceptions I throw are in relation to bad input 
 data, and they are to be caught at a slightly higher level
 of input processing.
I do not know the design that you are using, but it seems to me that instead of scope, the real problem is that you are using exceptions to communicate input errors between layers.
 My code has become try/catch-tastic, and I really don't like
 looking at it. It rather sickens me and reminds me of Java...
My knowledge of Java is a little rusty, but do you not do the same thing, using exceptions for control flow?
Aug 09 2014
prev sibling next sibling parent reply "Jacob Carlborg" <doob me.com> writes:
On Sunday, 3 August 2014 at 15:28:43 UTC, Manu via Digitalmars-d 
wrote:
 I'm trying to make better use of scope guards, but I find 
 myself belting
 out try/catch statements almost everywhere.
 I'm rather disappointed, because scope guards are advertised to 
 offer the
 promise of eliminating try/catch junk throughout your code, and 
 I'm just
 not finding that to be the practical reality.

 I think the core of the problem is that scope(failure) is 
 indiscriminate,
 but I want to filter it for particular exceptions. The other 
 issue is that
 you still need a catch() if you don't actually want the program 
 to
 terminate, which implies a try... :/

 One thing that may be leveraged to eliminate most catch blocks 
 is the
 existing ability to return from scope guard blocks, allowing to 
 gracefully
 return from a function while unwinding, akin to a catch.
 The problem then is that you can't handle specific exceptions.

 I'm thinking this would make all the difference:

 scope(failure, MyException e) // only executed for exceptions 
 of type
 MyException
 {
   writeln(e.msg); // can refer to the exception in this failure 
 block
   return failureValue; // and can gracefully return from the 
 function too
 }

 That would eliminate about 80% of my try/catch blocks.
That is exactly like a catch-block.
 The remaining suffer from the problem where I want to respond 
 to exceptions
 NOT of a specific type, ie, clean up in the case of an 
 unexpected/unknown
 exception.

 scope(failure, ~MyException)
 {
   // clean up, because some unexpected exception occurred that I
 don't/can't handle.
 }
That I can agree would be useful, but within a catch-block instead. You can always manually check the type of the exception. catch (Exception e) { if (auto myException = cast(MyException) e) // handle else // cleanup } Of course this logic could be nicely handled with AST macros ;)
 Is there already some mechanism to do this? I couldn't find 
 anything in the
 docs.
 It seems like an obvious thing to want to do.
It seems like you want to have a catch-block without a try-block. I think that would be useful. A catch-block without a try-block would implicitly add a try-block to the same scope as the catch-block or to the closest function body. Ruby has this and it's quite nice. void foo () { connectToDatabase(); catch (DatabaseException e) cleanup(); }
Aug 04 2014
parent reply Manu via Digitalmars-d <digitalmars-d puremagic.com> writes:
On 4 August 2014 17:13, Jacob Carlborg via Digitalmars-d <
digitalmars-d puremagic.com> wrote:

 On Sunday, 3 August 2014 at 15:28:43 UTC, Manu via Digitalmars-d wrote:

 I'm trying to make better use of scope guards, but I find myself belting
 out try/catch statements almost everywhere.
 I'm rather disappointed, because scope guards are advertised to offer the
 promise of eliminating try/catch junk throughout your code, and I'm just
 not finding that to be the practical reality.

 I think the core of the problem is that scope(failure) is indiscriminate,
 but I want to filter it for particular exceptions. The other issue is that
 you still need a catch() if you don't actually want the program to
 terminate, which implies a try... :/

 One thing that may be leveraged to eliminate most catch blocks is the
 existing ability to return from scope guard blocks, allowing to gracefully
 return from a function while unwinding, akin to a catch.
 The problem then is that you can't handle specific exceptions.

 I'm thinking this would make all the difference:

 scope(failure, MyException e) // only executed for exceptions of type
 MyException
 {
   writeln(e.msg); // can refer to the exception in this failure block
   return failureValue; // and can gracefully return from the function too
 }

 That would eliminate about 80% of my try/catch blocks.
That is exactly like a catch-block.
Yes, but there's no try block, and it is sequenced properly along with any other scheduled scope events. The remaining suffer from the problem where I want to respond to exceptions
 NOT of a specific type, ie, clean up in the case of an unexpected/unknown
 exception.

 scope(failure, ~MyException)
 {
   // clean up, because some unexpected exception occurred that I
 don't/can't handle.
 }
That I can agree would be useful, but within a catch-block instead. You can always manually check the type of the exception. catch (Exception e) { if (auto myException = cast(MyException) e) // handle else // cleanup }
catch can't appear on its own though... or are you suggesting that it should be possible? Of course this logic could be nicely handled with AST macros ;)
  Is there already some mechanism to do this? I couldn't find anything in
 the
 docs.
 It seems like an obvious thing to want to do.
It seems like you want to have a catch-block without a try-block. I think that would be useful. A catch-block without a try-block would implicitly add a try-block to the same scope as the catch-block or to the closest function body. Ruby has this and it's quite nice.
I was actually going to suggest that, except I deleted that part of my email thinking I was already getting too elaborate ;) void foo ()
 {
     connectToDatabase();

     catch (DatabaseException e)
         cleanup();
 }
Yeah, that. Except I think scope(failure, Exception e) also has a place; there are instances where you don't want to stop the unwind, but you do want to be able to retrieve some information from the exception during the unwind... useful for error recording or context sensitive recovery.
Aug 04 2014
parent "Jacob Carlborg" <doob me.com> writes:
On Monday, 4 August 2014 at 10:01:42 UTC, Manu via Digitalmars-d 
wrote:

 catch can't appear on its own though... or are you suggesting 
 that it
 should be possible?
Yes, that's what I'm suggesting.
 Yeah, that. Except I think scope(failure, Exception e) also has 
 a place;
 there are instances where you don't want to stop the unwind, 
 but you do
 want to be able to retrieve some information from the exception 
 during the
 unwind... useful for error recording or context sensitive 
 recovery.
Then rethrow the exception. -- /Jacob Carlborg
Aug 04 2014
prev sibling next sibling parent reply "Sean Kelly" <sean invisibleduck.org> writes:
On Sunday, 3 August 2014 at 15:28:43 UTC, Manu via Digitalmars-d
wrote:
 I'm thinking this would make all the difference:

 scope(failure, MyException e) // only executed for exceptions 
 of type
 MyException
 {
   writeln(e.msg); // can refer to the exception in this failure 
 block
   return failureValue; // and can gracefully return from the 
 function too
 }

 That would eliminate about 80% of my try/catch blocks.
 The remaining suffer from the problem where I want to respond 
 to exceptions
 NOT of a specific type, ie, clean up in the case of an 
 unexpected/unknown
 exception.

 scope(failure, ~MyException)
 {
   // clean up, because some unexpected exception occurred that 
 I don't/can't handle.
 }
The easiest thing would be to provide a thread-local reference to the currently in-flight exception. Then you could do whatever checking you wanted to inside the scope block.
Aug 04 2014
parent reply Jacob Carlborg <doob me.com> writes:
On 2014-08-05 01:10, Sean Kelly wrote:

 The easiest thing would be to provide a thread-local reference to
 the currently in-flight exception.  Then you could do whatever
 checking you wanted to inside the scope block.
That's quite clever. Can we do that? -- /Jacob Carlborg
Aug 05 2014
parent "Sean Kelly" <sean invisibleduck.org> writes:
On Tuesday, 5 August 2014 at 16:31:51 UTC, Jacob Carlborg wrote:
 On 2014-08-05 01:10, Sean Kelly wrote:

 The easiest thing would be to provide a thread-local reference 
 to
 the currently in-flight exception.  Then you could do whatever
 checking you wanted to inside the scope block.
That's quite clever. Can we do that?
I don't see why not. The exception handling code would need to set and clear the reference at the proper points, but this shouldn't be too difficult. We'd have to be careful how it's documented though. I think it's mostly applicable to Manu's case--specializing code in scope guards. For example: http://www.gotw.ca/gotw/047.htm
Aug 05 2014
prev sibling parent reply "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Sunday, 3 August 2014 at 15:28:43 UTC, Manu via Digitalmars-d 
wrote:
 I'm trying to make better use of scope guards, but I find 
 myself belting
 out try/catch statements almost everywhere.
 I'm rather disappointed, because scope guards are advertised to 
 offer the
 promise of eliminating try/catch junk throughout your code, and 
 I'm just
 not finding that to be the practical reality.
scope guards are for the occasions when you need to guarantee that something happens when either an exception isn't thrown (success), is thrown (failure), or regardless of whether one was thrown (exit). It's not intended for handling exceptions, just to reacting to their existence. So, it's primarily going to be used when you want to do something when an exception was thrown but don't care what was thrown or if you want to make sure that something happens regardless of whether an exception was thrown (in which case, it's a replacement for RAII or a finally block). I'd say that if you're trying to use scope in any situation where you'd try and handle an exception, then you're using it wrong. - Jonathan M Davis
Aug 07 2014
parent reply "Messenger" <dont shoot.me> writes:
On Thursday, 7 August 2014 at 20:54:02 UTC, Jonathan M Davis 
wrote:
 I'd say that if you're trying to use scope in any situation 
 where you'd try and handle an exception, then you're using it 
 wrong.
But it's super convenient.
Aug 07 2014
parent reply "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Thursday, 7 August 2014 at 20:59:45 UTC, Messenger wrote:
 On Thursday, 7 August 2014 at 20:54:02 UTC, Jonathan M Davis 
 wrote:
 I'd say that if you're trying to use scope in any situation 
 where you'd try and handle an exception, then you're using it 
 wrong.
But it's super convenient.
It fundamentally doesn't work to handle an exception with a scope guard. They rethrow the exception. It's clearly not what it was designed for. It was designed for making sure that certain things happen when an exception is thrown or regardless of whether an exception is thrown. But it's just not designed for actually handling exceptions. - Jonathan M Davis
Aug 07 2014
parent reply "Messenger" <dont shoot.me> writes:
On Friday, 8 August 2014 at 00:27:21 UTC, Jonathan M Davis wrote:
 On Thursday, 7 August 2014 at 20:59:45 UTC, Messenger wrote:
 On Thursday, 7 August 2014 at 20:54:02 UTC, Jonathan M Davis 
 wrote:
 I'd say that if you're trying to use scope in any situation 
 where you'd try and handle an exception, then you're using it 
 wrong.
But it's super convenient.
It fundamentally doesn't work to handle an exception with a scope guard. They rethrow the exception.
void fun() { scope(failure) return; throw new Exception(__FUNCTION__); } void main() { import std.exception; assertNotThrown(fun()); }
Aug 08 2014
parent reply "Idan Arye" <GenericNPC gmail.com> writes:
On Friday, 8 August 2014 at 08:37:37 UTC, Messenger wrote:
 On Friday, 8 August 2014 at 00:27:21 UTC, Jonathan M Davis 
 wrote:
 On Thursday, 7 August 2014 at 20:59:45 UTC, Messenger wrote:
 On Thursday, 7 August 2014 at 20:54:02 UTC, Jonathan M Davis 
 wrote:
 I'd say that if you're trying to use scope in any situation 
 where you'd try and handle an exception, then you're using 
 it wrong.
But it's super convenient.
It fundamentally doesn't work to handle an exception with a scope guard. They rethrow the exception.
void fun() { scope(failure) return; throw new Exception(__FUNCTION__); } void main() { import std.exception; assertNotThrown(fun()); }
Initially I thought this was a bug, but this seems intended since it doesn't work with `scope(exit)` - it yields the compiler error "Error: return statements cannot be in finally, scope(exit) or scope(success) bodies".
Aug 08 2014
parent reply "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Friday, 8 August 2014 at 12:22:49 UTC, Idan Arye wrote:
 On Friday, 8 August 2014 at 08:37:37 UTC, Messenger wrote:
 On Friday, 8 August 2014 at 00:27:21 UTC, Jonathan M Davis 
 wrote:
 On Thursday, 7 August 2014 at 20:59:45 UTC, Messenger wrote:
 On Thursday, 7 August 2014 at 20:54:02 UTC, Jonathan M Davis 
 wrote:
 I'd say that if you're trying to use scope in any situation 
 where you'd try and handle an exception, then you're using 
 it wrong.
But it's super convenient.
It fundamentally doesn't work to handle an exception with a scope guard. They rethrow the exception.
void fun() { scope(failure) return; throw new Exception(__FUNCTION__); } void main() { import std.exception; assertNotThrown(fun()); }
Initially I thought this was a bug, but this seems intended since it doesn't work with `scope(exit)` - it yields the compiler error "Error: return statements cannot be in finally, scope(exit) or scope(success) bodies".
I suspect that it says that because someone complained about the error talking about finally when they had used scope(exit) and not finally. The fact that scope statements get lower to try-catch-finally blocks allow for a few screwy things that were not intended. Whether those things will be left in or made illegal at this point is another matter, but I'm sure that it was never the intention that anyone be allowed to return from any kind of scope statement or do anything else which would cause the exception to not be rethrown. - Jonathan M Davis
Aug 08 2014
parent reply "Idan Arye" <GenericNPC gmail.com> writes:
On Saturday, 9 August 2014 at 00:17:07 UTC, Jonathan M Davis 
wrote:
 On Friday, 8 August 2014 at 12:22:49 UTC, Idan Arye wrote:
 On Friday, 8 August 2014 at 08:37:37 UTC, Messenger wrote:
 On Friday, 8 August 2014 at 00:27:21 UTC, Jonathan M Davis 
 wrote:
 On Thursday, 7 August 2014 at 20:59:45 UTC, Messenger wrote:
 On Thursday, 7 August 2014 at 20:54:02 UTC, Jonathan M 
 Davis wrote:
 I'd say that if you're trying to use scope in any 
 situation where you'd try and handle an exception, then 
 you're using it wrong.
But it's super convenient.
It fundamentally doesn't work to handle an exception with a scope guard. They rethrow the exception.
void fun() { scope(failure) return; throw new Exception(__FUNCTION__); } void main() { import std.exception; assertNotThrown(fun()); }
Initially I thought this was a bug, but this seems intended since it doesn't work with `scope(exit)` - it yields the compiler error "Error: return statements cannot be in finally, scope(exit) or scope(success) bodies".
I suspect that it says that because someone complained about the error talking about finally when they had used scope(exit) and not finally. The fact that scope statements get lower to try-catch-finally blocks allow for a few screwy things that were not intended. Whether those things will be left in or made illegal at this point is another matter, but I'm sure that it was never the intention that anyone be allowed to return from any kind of scope statement or do anything else which would cause the exception to not be rethrown. - Jonathan M Davis
If that was the case, the error would have said it's illegal to throw from "finally or scope bodies". The fact that it specifically specifies `scope(exit)` and `scope(success)` and leave out `scope(failure)` means that whoever wrote that error message made a conscious decision that it's OK to return in `scope(failure)`.
Aug 09 2014
next sibling parent "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> writes:
On Saturday, 9 August 2014 at 11:51:06 UTC, Idan Arye wrote:
 If that was the case, the error would have said it's illegal to 
 throw from "finally or scope bodies". The fact that it 
 specifically specifies `scope(exit)` and `scope(success)` and 
 leave out `scope(failure)` means that whoever wrote that error 
 message made a conscious decision that it's OK to return in 
 `scope(failure)`.
DMD src/statement.c:3621 says: if (sc->os && sc->os->tok != TOKon_scope_failure) error("return statements cannot be in %s bodies", Token::toChars(sc->os->tok)); So `scope(failure)` is explicitly exempted from the check.
Aug 09 2014
prev sibling parent "David Nadlinger" <code klickverbot.at> writes:
On Saturday, 9 August 2014 at 11:51:06 UTC, Idan Arye wrote:
 On Saturday, 9 August 2014 at 00:17:07 UTC, Jonathan M Davis 
 wrote:
 I suspect that it says that because someone complained about 
 the error talking about finally when they had used scope(exit) 
 and not finally. The fact that scope statements get lower to 
 try-catch-finally blocks allow for a few screwy things that 
 were not intended. Whether those things will be left in or 
 made illegal at this point is another matter, but I'm sure 
 that it was never the intention that anyone be allowed to 
 return from any kind of scope statement or do anything else 
 which would cause the exception to not be rethrown.

 - Jonathan M Davis
If that was the case, the error would have said it's illegal to throw from "finally or scope bodies". The fact that it specifically specifies `scope(exit)` and `scope(success)` and leave out `scope(failure)` means that whoever wrote that error message made a conscious decision that it's OK to return in `scope(failure)`.
Nope. The current wording of the error message resp. the source code for handling it simply resulted from a conservative fix for rewrite internals being leaked into the diagnostics: https://issues.dlang.org/show_bug.cgi?id=6889 In other words, nobody made a "conscious decision" that it is okay to return in scope(failure). It's just a consequence from the fact that it is rewritten into a catch block instead of finally {} like the others. Cheers, David
Aug 09 2014