November 22, 2013
On Friday, 22 November 2013 at 01:49:11 UTC, Shammah Chancellor wrote:
> On 2013-11-18 06:32:46 +0000, Andrei Alexandrescu said:
>> 
>> 1. Fix scope(failure) and then use it.
>> 
>> Andrei
>
> Huh?  Scope failure has no purpose here.  It does not CATCH the exception and prevent it from bubbling up the call chain.    Try/catch does do this.
>
> -Shammah

If the code is:

    scope(failure) assert(0);

Then it is a statement that the function doesn't throw. So there isn't a need to catch the exception, it is merely a way to state to the compiler "I've verified I know what I'm talking about and this function really doesn't ever throw."

Right now just having scope(failure) in the body is making this statement, and that is wrong.
November 22, 2013
On 11/21/13 6:07 PM, growler wrote:
> On Friday, 22 November 2013 at 01:49:11 UTC, Shammah Chancellor wrote:
>> On 2013-11-18 06:32:46 +0000, Andrei Alexandrescu said:
>>>
>>> 1. Fix scope(failure) and then use it.
>>>
>>> Andrei
>>
>> Huh?  Scope failure has no purpose here.  It does not CATCH the
>> exception and prevent it from bubbling up the call chain. Try/catch
>> does do this.
>>
>> -Shammah
>
> It does if you return from the scope(failure) block. The problem is you
> cannot mark the function as "nothrow"

I was thinking that scope(failure) could throw an Error.

Andrei

November 22, 2013
On 2013-11-22 02:07:36 +0000, growler said:

> On Friday, 22 November 2013 at 01:49:11 UTC, Shammah Chancellor wrote:
>> On 2013-11-18 06:32:46 +0000, Andrei Alexandrescu said:
>>> 
>>> 1. Fix scope(failure) and then use it.
>>> 
>>> Andrei
>> 
>> Huh?  Scope failure has no purpose here.  It does not CATCH the exception and prevent it from bubbling up the call chain.    Try/catch does do this.
>> 
>> -Shammah
> 
> It does if you return from the scope(failure) block. The problem is you cannot mark the function as "nothrow"
> 
> For example:
> ---
> void throwingFunction() {
>      throw new Exception("damn!");
> }
> 
> void someFunc() // nothrow
> {
>      scope(failure) {
>          writeln("Failed in someFunc()");
>          return;
>      }
>      throwingFunction();
> }
> 
> void main() {
>      try {
>          someFunc();
>          writeln("Yay, someFunc() is nothrow");
>      } catch(Exception e) {
>          writeln("An exception in main!");
>      }
> }
> 
> Output:
> 
> Failed in someFunc()
> Yay, someFunc() is nothrow.
> ---
> 
> But you cannot mark someFunc() as nothrow.

What!?  That shouldn't even be legal code!   See below for why:

void throwingFunction() {
    throw new Exception("damn!");
}

void someFunc() // nothrow
{
   scope(failure) { writeln("What?");} <-- NEVER EXECUTED?!
    scope(failure) {
        writeln("Failed in someFunc()");
        return;
    }
    throwingFunction();
}

void main() {
    try {
        someFunc();
        writeln("Yay, someFunc() is nothrow");
    } catch(Exception e) {
        writeln("An exception in main!");
    }
}

November 22, 2013
On Friday, 22 November 2013 at 02:35:40 UTC, Shammah Chancellor wrote:


...
>>> 
> What!?  That shouldn't even be legal code!   See below for why:
>
...

Maybe that's why it is considered broken? The first point was to 'fix' scope(failure) and then use it.

However, I don't know I haven't been following the discussion closely enough...
November 22, 2013
On Friday, 22 November 2013 at 02:17:18 UTC, Andrei Alexandrescu wrote:
> On 11/21/13 6:07 PM, growler wrote:
>> On Friday, 22 November 2013 at 01:49:11 UTC, Shammah Chancellor wrote:
>>> On 2013-11-18 06:32:46 +0000, Andrei Alexandrescu said:
>>>>
>>>> 1. Fix scope(failure) and then use it.
>>>>
>>>> Andrei
>>>
>>> Huh?  Scope failure has no purpose here.  It does not CATCH the
>>> exception and prevent it from bubbling up the call chain. Try/catch
>>> does do this.
>>>
>>> -Shammah
>>
>> It does if you return from the scope(failure) block. The problem is you
>> cannot mark the function as "nothrow"
>
> I was thinking that scope(failure) could throw an Error.
>
> Andrei

Yes, throwing an error makes more sensee than just return;


November 22, 2013
On Friday, 22 November 2013 at 02:35:40 UTC, Shammah Chancellor wrote:
> void someFunc() // nothrow
> {
>    scope(failure) { writeln("What?");} <-- NEVER EXECUTED?!
>     scope(failure) {
>         writeln("Failed in someFunc()");
>         return;
>     }
>     throwingFunction();
> }

That does exactly as expected:

void someFunc()
{
    try {
        try {
            throwingFunction();
        } catch {
            writeln("Failed in someFunc()");
            return;
        }
    } catch {
        writeln("What?");
    }
}
November 22, 2013
On 2013-11-22 03:03:15 +0000, Jesse Phillips said:

> On Friday, 22 November 2013 at 02:35:40 UTC, Shammah Chancellor wrote:
>> void someFunc() // nothrow
>> {
>> scope(failure) { writeln("What?");} <-- NEVER EXECUTED?!
>> scope(failure) {
>> writeln("Failed in someFunc()");
>> return;
>> }
>> throwingFunction();
>> }
> 
> That does exactly as expected:
> 
> void someFunc()
> {
>      try {
>          try {
>              throwingFunction();
>          } catch {
>              writeln("Failed in someFunc()");
>              return;
>          }
>      } catch {
>          writeln("What?");
>      }
> }

No.  scope(failure) is supposed to re-throw the exception.  Remember that the original proposal for scope(failure), etc. were using a stack of delegates.   The rewriting to try/catch is new and supposed to be functionally equivalent.  Return's from scope statements should be disallowed now.

November 22, 2013
On 2013-11-22 02:13:42 +0000, Jesse Phillips said:

> On Friday, 22 November 2013 at 01:49:11 UTC, Shammah Chancellor wrote:
>> On 2013-11-18 06:32:46 +0000, Andrei Alexandrescu said:
>>> 
>>> 1. Fix scope(failure) and then use it.
>>> 
>>> Andrei
>> 
>> Huh?  Scope failure has no purpose here.  It does not CATCH the exception and prevent it from bubbling up the call chain.    Try/catch does do this.
>> 
>> -Shammah
> 
> If the code is:
> 
>      scope(failure) assert(0);
> 
> Then it is a statement that the function doesn't throw. So there isn't a need to catch the exception, it is merely a way to state to the compiler "I've verified I know what I'm talking about and this function really doesn't ever throw."
> 
> Right now just having scope(failure) in the body is making this statement, and that is wrong.

Scope failure blocks should not be able to raise errors, or return except "out the end".

November 23, 2013
On Friday, 22 November 2013 at 21:48:14 UTC, Shammah Chancellor wrote:

[snip]
>
> No.  scope(failure) is supposed to re-throw the exception.

Where does it say that?

http://dlang.org/statement.html#ScopeGuardStatement

"... scope(failure) executes NonEmptyOrScopeBlockStatement when the scope exits due to exception unwinding. ..."


[snip]
> Return's from scope statements should be disallowed now.

I disagree. You cannot return or throw from a scope(exit) or scope(success) for obvious reasons, but how a program behaves when a scope fails should left to the programmer.

I might be at a DLL or C/C++ boundary and any exceptions (Throwable or otherwise) I do not want to escape out of the current scope.

I know I could use try-catch, but I find scope is just much easier to read.

Cheers G.
November 23, 2013
On 11/22/13 5:37 PM, growler wrote:
> On Friday, 22 November 2013 at 21:48:14 UTC, Shammah Chancellor wrote:
>
> [snip]
>>
>> No.  scope(failure) is supposed to re-throw the exception.
>
> Where does it say that?
>
> http://dlang.org/statement.html#ScopeGuardStatement
>
> "... scope(failure) executes NonEmptyOrScopeBlockStatement when the
> scope exits due to exception unwinding. ..."

It's implied. The scope is already being exited by means of an exception. If scope(failure) changed anything, _that_ would have been documented.

Anyhow we can be clearer in the docs.


Andrei