digitalmars.D - scope guards
- Manu via Digitalmars-d (32/32) Aug 03 2014 I'm trying to make better use of scope guards, but I find myself belting
- Mike Parker (7/16) Aug 03 2014 Scope guards are for when you don't need to handle exceptions. If you
- Manu via Digitalmars-d (6/21) Aug 03 2014 Well, then they're not particularly useful in practise. I'm finding that...
- Dicebot (11/17) Aug 03 2014 You may have coding style particularly alien to scope guards :)
- Manu via Digitalmars-d (23/35) Aug 03 2014 Sure, scope() may be useful for this, but it seems in my experience that
- Jacob Carlborg (15/32) Aug 04 2014 Why does it matter it has a lot of try/catch-blocks.
- Daniel Murphy (3/5) Aug 04 2014 But really, doesn't everyone?
- Jacob Carlborg (4/5) Aug 05 2014 Sure, but not to the point where I would go back to C style error handli...
- Manu via Digitalmars-d (20/41) Aug 04 2014 I hate pointless brace and indentation spam, I feel it severely damages ...
- Jacob Carlborg (11/32) Aug 05 2014 If you want to the if-statements to have the same semantics won't those
- Dicebot (6/11) Aug 04 2014 Destructors only work if:
- Atila Neves (3/14) Aug 05 2014 b) And even then, struct destruction can be non-deterministic if
- Manu via Digitalmars-d (5/21) Aug 05 2014 'scope' class destruction is deterministic though right?
- Dicebot (9/13) Aug 05 2014 scope classes are not supported anymore and considered D1 legacy
- Daniel Murphy (3/6) Aug 05 2014 I do, for DDMD. The only thing wrong with them is that they're not safe...
- Jacob Carlborg (7/10) Aug 05 2014 Yes, but you don't know in the destructor of "Foo" if it was used in a
- Sebastiaan Koppe (7/12) Aug 09 2014 I do not know the design that you are using, but it seems to me
- Jacob Carlborg (24/70) Aug 04 2014 That is exactly like a catch-block.
- Manu via Digitalmars-d (15/76) Aug 04 2014 Yes, but there's no try block, and it is sequenced properly along with a...
- Jacob Carlborg (6/17) Aug 04 2014 Yes, that's what I'm suggesting.
- Sean Kelly (5/26) Aug 04 2014 The easiest thing would be to provide a thread-local reference to
- Jacob Carlborg (4/7) Aug 05 2014 That's quite clever. Can we do that?
- Sean Kelly (7/13) Aug 05 2014 I don't see why not. The exception handling code would need to
- Jonathan M Davis (15/23) Aug 07 2014 scope guards are for the occasions when you need to guarantee
- Messenger (3/6) Aug 07 2014 But it's super convenient.
- Jonathan M Davis (8/14) Aug 07 2014 It fundamentally doesn't work to handle an exception with a scope
- Messenger (9/19) Aug 08 2014 void fun() {
- Idan Arye (5/26) Aug 08 2014 Initially I thought this was a bug, but this seems intended since
- Jonathan M Davis (11/39) Aug 08 2014 I suspect that it says that because someone complained about the
- Idan Arye (8/48) Aug 09 2014 If that was the case, the error would have said it's illegal to
- "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> (6/12) Aug 09 2014 DMD src/statement.c:3621 says:
- David Nadlinger (11/30) Aug 09 2014 Nope. The current wording of the error message resp. the source
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
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
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: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...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.
Aug 03 2014
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
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: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 inWell, 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.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 thoughYeah, I can't imagine a use for it either.
Aug 03 2014
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 JavaSo 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
"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
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
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 theyI 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 Javaare 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.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 justSo 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.It will produce flat sequential code which is easier to follow. So... why not make scope guards more useful? It wouldn't be hard.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.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.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.
Aug 04 2014
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
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
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:b) And even then, struct destruction can be non-deterministic if they happen to be in a dynamic array...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 05 2014
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:'scope' class destruction is deterministic though right? http://dlang.org/statement.html : there are examples of stuff like this: scope Foo f = new Foo();On Monday, 4 August 2014 at 04:09:07 UTC, Manu via Digitalmars-d wrote:b) And even then, struct destruction can be non-deterministic if they happen to be in a dynamic array...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 05 2014
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 Many of dlang.org documentation pages that are not generated from actual code are outdated in that regard.
Aug 05 2014
"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
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
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
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
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: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 exceptionsI'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.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 ;)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 }Is there already some mechanism to do this? I couldn't find anything inI was actually going to suggest that, except I deleted that part of my email thinking I was already getting too elaborate ;) void foo ()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.{ 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
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
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
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
On Tuesday, 5 August 2014 at 16:31:51 UTC, Jacob Carlborg wrote:On 2014-08-05 01:10, Sean Kelly wrote: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.htmThe 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?
Aug 05 2014
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
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
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: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 DavisI'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
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:void fun() { scope(failure) return; throw new Exception(__FUNCTION__); } void main() { import std.exception; assertNotThrown(fun()); }On Thursday, 7 August 2014 at 20:54:02 UTC, Jonathan M Davis wrote:It fundamentally doesn't work to handle an exception with a scope guard. They rethrow the exception.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 08 2014
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: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".On Thursday, 7 August 2014 at 20:59:45 UTC, Messenger wrote:void fun() { scope(failure) return; throw new Exception(__FUNCTION__); } void main() { import std.exception; assertNotThrown(fun()); }On Thursday, 7 August 2014 at 20:54:02 UTC, Jonathan M Davis wrote:It fundamentally doesn't work to handle an exception with a scope guard. They rethrow the exception.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 08 2014
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: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 DavisOn Friday, 8 August 2014 at 00:27:21 UTC, Jonathan M Davis wrote: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".On Thursday, 7 August 2014 at 20:59:45 UTC, Messenger wrote:void fun() { scope(failure) return; throw new Exception(__FUNCTION__); } void main() { import std.exception; assertNotThrown(fun()); }On Thursday, 7 August 2014 at 20:54:02 UTC, Jonathan M Davis wrote:It fundamentally doesn't work to handle an exception with a scope guard. They rethrow the exception.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 08 2014
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: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)`.On Friday, 8 August 2014 at 08:37:37 UTC, Messenger 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 DavisOn Friday, 8 August 2014 at 00:27:21 UTC, Jonathan M Davis wrote: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".On Thursday, 7 August 2014 at 20:59:45 UTC, Messenger wrote:void fun() { scope(failure) return; throw new Exception(__FUNCTION__); } void main() { import std.exception; assertNotThrown(fun()); }On Thursday, 7 August 2014 at 20:54:02 UTC, Jonathan M Davis wrote:It fundamentally doesn't work to handle an exception with a scope guard. They rethrow the exception.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 09 2014
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
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: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, DavidI 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 DavisIf 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