Generalize `elif-else-finally` to all compound statements

I really appreciate people taking the time to propose ideas. I’m having trouble understanding the actual proposal here. The first post has <HEAD> which I don’t understand, and comma-separated clauses which aren’t clear to me. Ideas are much easier to discuss if the semantics are clearly spelled out in English, or in equivalent Python examples.

Which gets me to this, which is very clear:

while True:
    ...
finally:
    ...
# Equivalent to
try:
    while True:
        ...
finally:
    ...

Personally, I don’t see the need to compress down to the while/finally style. Spelling it out with try is more explicit and clearer, and how often will this construct prove useful?

But there is a larger problem with this example. Will this code run the finally clause or not?

while 1/0:
    print("Never")
finally:
    print("Done")

The “equivalent Python” code would run the finally, but it’s not clear to me that the compressed version would.

-1 from me.

2 Likes

And I appreciate people taking time to read them. Apologies if it wasn’t very clearly expressed. I improved it as much as I could without changing it completely.

This is a very good point. Although conceptually it makes sense, it becomes ambiguous from users perspective.

Yeah, it seems that this is what this has narrowed down to so far - adding elif to cases where else can be used.

Although not major, finally has complications and is probably best to be left out. Also, elif cases have more hits in code searches than the rest combined.

Also, from experience, this is what I have found myself needing most. I type else, but being left confused by why I can not use elif as well.

Finally, this reduces complexity of the whole proposal by a factor. The presence of else has all the bases covered for elif addition.

I dislike the possibility that a finally may be overlooked just because there is no try. Imagine reading this function to see what happens if x is None …

def func(x, y):
    if x is None:
        return False
    ...

Seems to be obvious, but wait … must read to the end:

def func(x, y):
    if x is None:
        return False
    ...
    finally:
        if y is None:
            shutdown()
4 Likes

Readability-wise, the try ... elif construct does have the benefit of sometimes allowing better grouping of logic with the error-handling control flow at the same level. Whether this is desirable or not depends on situation.

try:
    result = get_result()
except SomeError as se:
    # An error occurred, such as file not found
    report_error(se)
elif foo is None:
    report_no_result()
else:
    do_something_useful(result)

How well this benefit translates into the case of looping constructs (for, while) is less certain. It also remains to see whether the proposed treatment of elif actually simplifies implementation on part of the compiler.

Neither do I appreciate the finallly after if/while/for. Every time I see a finally after a try block I tend to stop and think: what can fail so messy in the above try block that requires a finally to cleanup.

try ... finally just has too much “magic” to be made implicit, and the proposed while ... finally is pehaps too much action-at-a-distance. The 1990s Python adage of “explicit is better than implicit” may not necessarily hold true these days, but still I believe in this case the notion has some merit.

1 Like

Even if it will, it is not of significance. Best to leave this as part of “small benefits that might happen during implementation” and not part of the decision regarding this.

This seems to be the consensus so far and I agree. Thus, I have reduced this proposal to: `while-elif-else`, `for-elif-else`, `try-except-elif-else` - #8 by elis.byberi

Note that else in the if statement, in a loop statement and in the try statement are three very different things.

  • else after if is executed if the if condition is false.
  • else after a loop is executed if no break was executed in the loop body.
  • else after try is executed if no exceptions were raised in the try block.

It is coencidence that the same keyword is used in these cases. Maybe if Guido had used Dutch words, they would have been three different keywords.

2 Likes

This is very true. The pre-condition is different among all 3 cases.

However, there is more similarity to them than is currently presented. I.e.:

All of them are executed if some condition is NOT satisfied.

So one POV how I see this proposal is the attempt to put these under the same umbrella as appropriate by making clauses that are entered when some condition is NOT satisfied consistent.

Currently it is emphasised that these are completely different cases with individual syntaxes, thus difficulties in learning them.

Addition of elif could shift this POV by revealing their similarity. E.g. It could be taught as:

elif-else clause combination is entered when a certain condition in the initial statement-clause construct is NOT satisfied. These conditions are different for different cases: if, while & for and try-except.

So the syntax is the same, functionality is the same - there is a pattern that supports learning more functionality with less concepts to digest.

So far what I have observed is that there is a major difficulty in presenting this proposal because people are not comfortable with existing else in for and while statements.

I think elif addition together with a slight change of the way to think about it could address this issue.

To put it together:

elif-else clause combination is entered when a certain condition in the initial statement-clause construct is NOT satisfied.

These conditions are different for different cases: if, while & for and try-except.

  1. if: elif-else is entered if condition in if condition is NOT satisfied
  2. while & for: elif-else is entered if NO break was executed in the loop body
  3. try-except: elif-else is entered if NO exceptions were raised in the try body

Well, yes. But what has that to do with combining an “if” with them? You’re not proposing adding an “eltry” or “elwhile” clause. Why should they be combined with a different clause?

You’re stretching for a justification for something that doesn’t really add much value. A for-else or while-else is very different from an if-else and you don’t chain them the way you would with if-else-if-else-if.

But I do. I think about it in the way I described in Generalize `elif-else-finally` to all compound statements - #28 by dg-pb.

And it makes my life easy.

While I see that many are having difficulties getting their heads around else in for and while statements.

How much it adds for everyone is what I am trying to figure out. But it has 3 parts:

  1. Elimination of existing nested statements
  2. Flexibility improvement of try/for/while statements
  3. Consistency of elif-else clauses across all the statements that support these. Which does simplify things to me personally as I don’t need to remember where I can use elif and where I can not.
  1. Never really been all that much of a goal for Python, but if it were to be, for x in iterable if cond: is a much more valuable tool, and that has had little if any support.
  2. Not really. They’re already just as flexible, you just need the additional indentation level.
  3. As previously stated, it’s not adding more consistency. It’s worsening the consistency, since now you have this weird notion of a try/if chain but you can only have try as the first one. And people don’t do try/if chains the way if/if/if chains are done.

So, no. It doesn’t add value.

I see that, but this is very different case and it introduces something completely new in syntax, thus doesn’t have a predetermined place, while what I am proposing is a transfer of functionality that already exists from one case to another.

The combination of compound statements is as flexible, but flexibility of a single compound statement is less

What notion? I don’t think I do.

Well duh. You are losing me here. You are arguing with something that I have neither said nor think.

I don’t understand what chains you are talking about, but what I have proposed here is:

try:
except:
elif:
elif:
else:

And people do do these. I have provided a specific search count which contains little to no false positives.