September 28, 2016
On 9/27/2016 11:50 PM, John Colvin wrote:
> 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().

Yeah, you're right. I should have tested it. A flag will fix it :-)

September 28, 2016
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
> ```

Thanks!

There is also useful for/else construct in Python

https://docs.python.org/2/tutorial/controlflow.html#break-and-continue-statements-and-else-clauses-on-loops

I'd like to see it in D.

September 28, 2016
On 9/27/16 11: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
> ```

Thanks for the submission. I made on pass through the document and it needs some work.

* Please remove colloquialisms. Characterizations such as "fantastically useful" are unlikely to be a convincing motivator and have no place in a DIP.

* The motivation section should showcase examples that currently are not possible or are contorted in D, followed by their alternative implementation using the proposed feature. At best, the example would be taken from existing code (e.g. found in dub, phobos, etc). Next best is code that defines a plausible artifact.

* The motivation section should also hypothesize on why the feature did not get traction in other languages than Python (Java, C++, C#). Also, it would be useful to show why D does need the feature even though it already has richer exception handing mechanisms by means of "scope".

* The "Description" section should be more detailed and less casual. The grammar changes should be shown in a syntax similar to the current grammar definition.

* I saw in the forum that the "else" clause is supposed to run in the scope of the "try" statement, but that is not mentioned in the proposal. Even though that is the semantics in Python, that should be explicit in the document. The proposal should be standalone and fully specified without knowing Python or perusing external links.

* The fact above (the "else" clause continues the scope of the statement after "try") is surprising, considering that the "catch" and "finally" clauses introduce their own scopes. The irregularity may confuse users. If the "else" clause is defined to introduce its own scope, it seems the advantages of the proposal are diminished.

* The "Breaking changes" section should include how the following change in semantics would be addressed. Consider:

  try
    if (expression)
        try { ... }
        catch (Exception) { ... }
    else { ... }
  finally { ... }

This code is currently legal and binds the "else" clause to the "if" and the "finally" to the first "try". The proposed feature will bind the "else" and the "finally" to the second try and then probably fail to compile because there is no "catch" or "finally" matching the first "try".

* The example by Jack Stouffer should be also shown translated in current and proposed D.

* The example with "do_a_thing()" etc. is superfluous because it does not illustrate why one would want to "write code like this". Please focus on examples that are meaningful and easy with the feature, difficult without.

* My understanding is the last example (D rendition) can be expressed like this:

scope(exit) do_this_always();
bool success;
try
{
    do_a_thing();
    success = true;
}
catch(Exception exception)
{
    handle_error();
}
finally
{
   if(success)
   {
       depends_on_success_of_thing();
   }
}

There are further simplifications if it is known that handle_error() finishes the flow (by either throwing or an early return). Again, motivating examples would at best show that this pattern is frequent enough and awkward enough to justify the language addition.


Andrei

September 28, 2016
On Wednesday, 28 September 2016 at 07:47:32 UTC, Andrei Alexandrescu wrote:
> scope(exit) do_this_always();
> bool success;
> try
> {
>     do_a_thing();
>     success = true;
> }
> catch(Exception exception)
> {
>     handle_error();
> }
> finally
> {
>    if(success)
>    {
>        depends_on_success_of_thing();
>    }
> }

Why not an optional syntax like:

finally(bool thrown)
{

}

?
September 28, 2016
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:

I support this addition because, while it's possible to mimic this behavior now, this makes code cleaner.

I will also post some rationale from the Python docs:

"The use of the else clause is better than adding additional code to the try clause because it avoids accidentally catching an exception that wasn’t raised by the code being protected by the try/except statement."

https://docs.python.org/3/tutorial/errors.html#handling-exceptions
September 28, 2016
On 9/28/16 12:19 PM, Jack Stouffer wrote:
> 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:
>
> I support this addition because, while it's possible to mimic this
> behavior now, this makes code cleaner.

This rough count:

git grep '^ *try' | wc -l

reveals 187 uses of "try" in Phobos. Of these, how many could be improved? Looking into that and also on a selection of dub projects would strengthen the argument. Assertions such as "makes the code cleaner" are likely to add value only if backed up by evidence (case studies, realistic examples).

> I will also post some rationale from the Python docs:
>
> "The use of the else clause is better than adding additional code to the
> try clause because it avoids accidentally catching an exception that
> wasn’t raised by the code being protected by the try/except statement."
>
> https://docs.python.org/3/tutorial/errors.html#handling-exceptions

Porting motivating arguments from other languages is helpful only if put in the context of D, e.g. Python does not have "scope" statements, which makes matters different across the two languages.


Andrei

September 28, 2016
On Wednesday, 28 September 2016 at 10:45:11 UTC, Andrei Alexandrescu wrote:
> Assertions such as "makes the code cleaner" are likely to add value only if backed up by evidence (case studies, realistic examples).

This is based on my anecdotal experience. I also posted an example in the original thread which was included in the DIP.

> Porting motivating arguments from other languages is helpful only if put in the context of D, e.g. Python does not have "scope" statements, which makes matters different across the two languages.

It was already shown in this thread how scope statements do not achieve the same effect as the try/else statement; the point still stands.
September 28, 2016
On Wednesday, 28 September 2016 at 07:33:48 UTC, ikod wrote:
> Thanks!
>
> There is also useful for/else construct in Python
>
> https://docs.python.org/2/tutorial/controlflow.html#break-and-continue-statements-and-else-clauses-on-loops
>
> I'd like to see it in D.

While I appreciate being able to use for/else and while/else in Python, in D using gotos provides a more flexible (if more archaic) solution.

But if we were to borrow else from Python for loops - which isn't a terrible idea since gotos are messy and make code harder to read - I'd suggest augmenting the construct with another block that evaluates only when the loop _wasn't_ broken.

Make a DIP!
September 28, 2016
On Wednesday, 28 September 2016 at 07:47:32 UTC, Andrei Alexandrescu wrote:
> * Please remove colloquialisms. Characterizations such as "fantastically useful" are unlikely to be a convincing motivator and have no place in a DIP.
>
> * The "Description" section should be more detailed and less casual. The grammar changes should be shown in a syntax similar to the current grammar definition.

These were not documented as a requirement anywhere that I saw. I'd have been happy to comply, if I had known this was the practice.

I don't know enough about how D is compiled to speak meaningfully about implementation details.

I am clearly not the only one who's convinced this is a useful feature. I welcome you or anyone else who can more effectively express the idea to make their own contributions to the DIP.

On Wednesday, 28 September 2016 at 07:47:32 UTC, Andrei Alexandrescu wrote:
> * I saw in the forum that the "else" clause is supposed to run in the scope of the "try" statement, but that is not mentioned in the proposal. Even though that is the semantics in Python, that should be explicit in the document. The proposal should be standalone and fully specified without knowing Python or perusing external links.
>
> * The fact above (the "else" clause continues the scope of the statement after "try") is surprising, considering that the "catch" and "finally" clauses introduce their own scopes. The irregularity may confuse users. If the "else" clause is defined to introduce its own scope, it seems the advantages of the proposal are diminished.

It was an idea that was raised, yes.

If catch and finally don't continue the scope of try, then neither should else.

That said, it might be preferable if they all did continue try's scope. But this would be a distinct and separate change.

> * The "Breaking changes" section should include how the following change in semantics would be addressed. Consider:
>
>   try
>     if (expression)
>         try { ... }
>         catch (Exception) { ... }
>     else { ... }
>   finally { ... }
>
> This code is currently legal and binds the "else" clause to the "if" and the "finally" to the first "try". The proposed feature will bind the "else" and the "finally" to the second try and then probably fail to compile because there is no "catch" or "finally" matching the first "try".

This possibility hadn't occurred to me. Is that really legal?

If so, I'd argue the old behavior should be maintained and also that people shouldn't write such ambiguous code.



September 28, 2016
On Wednesday, 28 September 2016 at 10:50:00 UTC, Jack Stouffer wrote:
> On Wednesday, 28 September 2016 at 10:45:11 UTC, Andrei Alexandrescu wrote:
>> Assertions such as "makes the code cleaner" are likely to add value only if backed up by evidence (case studies, realistic examples).
>
> This is based on my anecdotal experience. I also posted an example in the original thread which was included in the DIP.
>
>> Porting motivating arguments from other languages is helpful only if put in the context of D, e.g. Python does not have "scope" statements, which makes matters different across the two languages.
>
> It was already shown in this thread how scope statements do not achieve the same effect as the try/else statement; the point still stands.

Yes, scope can't immitate catch else without a flag. It doesn't follow that therefore we need catch else.

What realistic code will be made significantly better by having it? Under what circumstances is structuring the code differently or using a flag so unacceptable that a new language feature is worth it?

That's the question that needs answering.