September 27, 2016 DIP 1002 (TryElseExpression) added to the queue | ||||
---|---|---|---|---|
| ||||
https://github.com/dlang/DIPs/blob/master/DIPs/DIP1002.md PR: https://github.com/dlang/DIPs/pull/43 Abstract: In Python, the try/catch/finally syntax is augmented with an additional clause, termed else. It is a fantastically useful addition to the conventional syntax. It works like this: ``` try: do_something() except Exception as e: pass # Runs when an error inheriting from Exception was raised else: pass # Runs when no error was raised finally: pass # Runs unconditionally, evaluates last ``` |
September 27, 2016 Re: DIP 1002 (TryElseExpression) added to the queue | ||||
---|---|---|---|---|
| ||||
Posted in reply to Dicebot | On Tuesday, September 27, 2016 09:30:10 Dicebot via Digitalmars-d wrote:
> https://github.com/dlang/DIPs/blob/master/DIPs/DIP1002.md
>
> PR: https://github.com/dlang/DIPs/pull/43
>
> Abstract:
>
> In Python, the try/catch/finally syntax is augmented with an additional clause, termed else. It is a fantastically useful addition to the conventional syntax. It works like this:
>
> ```
> try:
> do_something()
> except Exception as e:
> pass # Runs when an error inheriting from Exception was
> raised
> else:
> pass # Runs when no error was raised
> finally:
> pass # Runs unconditionally, evaluates last
> ```
And why not just put the code that would go in the else at the end of the try block? Just like with this proposed else, the code would only run if the preceding code didn't throw any exceptions. This just seems like an attempt to make D more like python rather than to add anything useful.
- Jonathan M Davis
|
September 27, 2016 Re: DIP 1002 (TryElseExpression) added to the queue | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jonathan M Davis | On Tuesday, 27 September 2016 at 09:48:42 UTC, Jonathan M Davis wrote:
> On Tuesday, September 27, 2016 09:30:10 Dicebot via Digitalmars-d wrote:
>> https://github.com/dlang/DIPs/blob/master/DIPs/DIP1002.md
>>
>> PR: https://github.com/dlang/DIPs/pull/43
>>
>> Abstract:
>>
>> In Python, the try/catch/finally syntax is augmented with an additional clause, termed else. It is a fantastically useful addition to the conventional syntax. It works like this:
>>
>> ```
>> try:
>> do_something()
>> except Exception as e:
>> pass # Runs when an error inheriting from Exception was
>> raised
>> else:
>> pass # Runs when no error was raised
>> finally:
>> pass # Runs unconditionally, evaluates last
>> ```
>
> And why not just put the code that would go in the else at the end of the try block? Just like with this proposed else, the code would only run if the preceding code didn't throw any exceptions. This just seems like an attempt to make D more like python rather than to add anything useful.
>
> - Jonathan M Davis
Exceptions thrown in the `else` clause are not caught in the catch/expect clauses. This gives you finer grained control:
try {
auto f1 = File("f1.txt");
} catch (ErrnoException) {
// f1.txt not found? no biggie...
} else {
// This won't happen if we can't open f1.txt
// If we can't open f2 we don't want to catch the exception:
auto f2 = File("f2.txt", "w");
// Do stuff with f1 and f2
}
// This will still happen even if we can't open f1.txt
BTW, if this feature is ever implemented in D, it's important that the else clause will continue the try clause's scope.
|
September 27, 2016 Re: DIP 1002 (TryElseExpression) added to the queue | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jonathan M Davis | On Tuesday, 27 September 2016 at 09:48:42 UTC, Jonathan M Davis wrote:
> And why not just put the code that would go in the else at the end of the try block? Just like with this proposed else, the code would only run if the preceding code didn't throw any exceptions. This just seems like an attempt to make D more like python rather than to add anything useful.
>
> - Jonathan M Davis
This is a commonly-used tool that makes code more readable and cuts down on programmer error.
It's far more concise and digestible than the functional equivalent, which is _not_ to put the code at the end of the `try` block, it's to put it in the `finally` block - refer to the DIP's example for how that works.
This is the most important difference between using `else` and doing what you described: Exceptions thrown by the code in the `else` block are not caught by the `catch` statements intended to handle errors by the operation in the `try` block, but not to handle errors resulting from attempting to handle a success state.
|
September 27, 2016 Re: DIP 1002 (TryElseExpression) added to the queue | ||||
---|---|---|---|---|
| ||||
Posted in reply to Idan Arye | On Tuesday, 27 September 2016 at 10:05:20 UTC, Idan Arye wrote:
> BTW, if this feature is ever implemented in D, it's important that the else clause will continue the try clause's scope.
The catch and finally clauses do currently continue the scope, right? (If they don't, they probably should, too.)
|
September 27, 2016 Re: DIP 1002 (TryElseExpression) added to the queue | ||||
---|---|---|---|---|
| ||||
Posted in reply to Dicebot | On Tuesday, 27 September 2016 at 09:30:10 UTC, Dicebot wrote:
> https://github.com/dlang/DIPs/blob/master/DIPs/DIP1002.md
>
> PR: https://github.com/dlang/DIPs/pull/43
>
> Abstract:
>
> In Python, the try/catch/finally syntax is augmented with an additional clause, termed else. It is a fantastically useful addition to the conventional syntax. It works like this:
>
> ```
> try:
> do_something()
> except Exception as e:
> pass # Runs when an error inheriting from Exception was raised
> else:
> pass # Runs when no error was raised
> finally:
> pass # Runs unconditionally, evaluates last
> ```
What's annoying is that we already have finally, which can be reproduced with other language features:
{
/*finally*/ scope (exit) {}
try {
do_something();
} catch (Exception e) {}
}
but we don't (yet) have catch else, which is harder to immitate. Options are:
A) the else clause is nothrow (in which case it can just go last inside the try)
or
B) store a flag and have to use immitation finally:
{
/*finally*/ scope (exit) {}
bool exceptionThrown = false;
try {
doSomething();
} catch (Exception e) {
exceptionThrown = true;
}
/*else*/ if (!exceptionThrown) {}
}
|
September 27, 2016 Re: DIP 1002 (TryElseExpression) added to the queue | ||||
---|---|---|---|---|
| ||||
Posted in reply to John Colvin | On 9/27/16 6:55 AM, John Colvin wrote: > > What's annoying is that we already have finally, which can be > reproduced with other language features: > > { > /*finally*/ scope (exit) {} > try { > do_something(); > } catch (Exception e) {} > } Hm... I always thought scope(exit) is lowered to: try { } finally { // scope exit code here } Which one is the building block? ;) > but we don't (yet) have catch else, which is harder to immitate. Options > are: > A) the else clause is nothrow (in which case it can just go last inside > the try) > or > B) store a flag and have to use immitation finally: > > { > /*finally*/ scope (exit) {} > bool exceptionThrown = false; > try { > doSomething(); > } catch (Exception e) { > exceptionThrown = true; > } > /*else*/ if (!exceptionThrown) {} > } I tried a few things, including scope(success), but it doesn't seem doable without an extra piece of data. Essentially, the else clause allows you to split your try block into catch-protected code, and non-catch-protected code. Seems like a worthwhile addition, if easily implemented. -Steve |
September 27, 2016 Re: DIP 1002 (TryElseExpression) added to the queue | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | On 9/27/2016 6:22 AM, Steven Schveighoffer wrote:
> Hm... I always thought scope(exit) is lowered to:
>
> try
> {
> }
> finally
> {
> // scope exit code here
> }
>
> Which one is the building block? ;)
try/catch/finally is the building block, other constructs are lowered to that.
|
September 27, 2016 Re: DIP 1002 (TryElseExpression) added to the queue | ||||
---|---|---|---|---|
| ||||
Posted in reply to Dicebot | On 9/27/2016 2:30 AM, Dicebot wrote: > https://github.com/dlang/DIPs/blob/master/DIPs/DIP1002.md > > PR: https://github.com/dlang/DIPs/pull/43 > > Abstract: > > In Python, the try/catch/finally syntax is augmented with an additional clause, > termed else. It is a fantastically useful addition to the conventional syntax. > It works like this: > > ``` > try: > do_something() > except Exception as e: > pass # Runs when an error inheriting from Exception was raised > else: > pass # Runs when no error was raised > finally: > pass # Runs unconditionally, evaluates last > ``` The DIP says that a state variable is currently necessary, but that is incorrect: try { scope (exit) { Runs unconditionally, evaluates last } scope (success) { runs when no error was raised } do_something(); } catch (Exception e) { Runs when an error inheriting from Exception was raised } Implementation: The try/catch/else/finally could be 'lowered' into the above form. These references should be included in the DIP: http://dlang.org/spec/statement.html#ScopeGuardStatement http://dlang.org/exception-safe.html My opinion: Due to the existence of the ScopeGuardStatement, I feel this new syntax is redundant and needs a much better justification. |
September 28, 2016 Re: DIP 1002 (TryElseExpression) added to the queue | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | On Wednesday, 28 September 2016 at 04:23:56 UTC, Walter Bright wrote:
> On 9/27/2016 2:30 AM, Dicebot wrote:
>> https://github.com/dlang/DIPs/blob/master/DIPs/DIP1002.md
>>
>> PR: https://github.com/dlang/DIPs/pull/43
>>
>> Abstract:
>>
>> In Python, the try/catch/finally syntax is augmented with an additional clause,
>> termed else. It is a fantastically useful addition to the conventional syntax.
>> It works like this:
>>
>> ```
>> try:
>> do_something()
>> except Exception as e:
>> pass # Runs when an error inheriting from Exception was raised
>> else:
>> pass # Runs when no error was raised
>> finally:
>> pass # Runs unconditionally, evaluates last
>> ```
>
> The DIP says that a state variable is currently necessary, but that is incorrect:
>
> try
> {
> scope (exit)
> {
> Runs unconditionally, evaluates last
> }
> scope (success)
> {
> runs when no error was raised
> }
> do_something();
> }
> catch (Exception e)
> {
> Runs when an error inheriting from Exception was raised
> }
That's not the same. Exceptions thrown in the success block can be caught by the catch. That scope (success) block is equivalent to just putting its contents immediately after do_something().
|
Copyright © 1999-2021 by the D Language Foundation