Skip to content
This repository has been archived by the owner on Nov 21, 2022. It is now read-only.

Change to a flat indentation scheme? #133

Open
gvanrossum opened this issue Jul 11, 2020 · 6 comments
Open

Change to a flat indentation scheme? #133

gvanrossum opened this issue Jul 11, 2020 · 6 comments

Comments

@gvanrossum
Copy link
Owner

gvanrossum commented Jul 11, 2020

The arguments against this are not very strong, and it would solve the main problem with else (see #89). There is currently some discussion on python-dev regarding this (though no clear winner).

Note that the contents of the match statement is non-standard regardless how you indent it: it's not a block of statements, it's an (indented) list of case blocks.

Note that I would be dead set against the variant

match:
    expr
case pat:
    ...

since that would end up being written as

match: expr
case pat:
    ...

and that just doesn't read very well. But this reads fine:

match expr:
case pat:
    ...
@natelust
Copy link
Contributor

Personally I prefer the cases to be indented as it visually groups that these are all branches on one variable. Contrast this with if statements that could use a completely different variable in each branch arm. In the later case it is commonly understood that the block beneath an if corresponds to whatever variable was in the if expression. Because of this is is natural to have a single if statement, or many if, elif grouped together.

As python conveys meaning with formatting it is nice to see at a glance the grouping of expressions. Consider the case where there might be two match statements consecutively, with many cases in each. It might be easy to overlook that the second match has begun while scrolling. This is less of a problem with multiple if groups consecutively as each statement contains the variable one would need to consider for context.

@gvanrossum
Copy link
Owner Author

Re-reading Nate's comment, I realize that there may be a reason why this is so hard to get agreement on. Some people (e.g. myself) think of if and match as control flow statements that translate essentially into tests and jump instructions. (When I learned programming there were still languages around that used "computed goto"; I guess this education still determines my POV 45 years later.) Others see them as higher-level selection operations. Given his comment above I think Nate falls into this category, and I suspect in general folks who argue for indenting else with match do.

These two things are completely isomorphic in terms of how execution proceeds. For example, any compiler would generate the same code regardless of how we indent else, and an decent optimizing compiler would also generate the same code for case _. But people think about it differently, and I believe code written one way or another is easier to follow for people whose way of thinking matches that of the author of the code.

So it would be better if the two way of thinking about it resulted in the code being written the same way -- that way there won't be a possibility of miscommunication even if the author and the reader use a different POV.

I guess this is one of the reasons why TOOWTDI is such an important principle (even though it's often impossible to follow strictly).

But I have no stronger conclusion that my opening comment for this issue: we either should have no else (since no matter how we indent it, half the people won't like it -- and having both options would be worse), or we should switch to a flat indentation scheme, and then we may add else.

Now, even if we had a flat indentation scheme with an else clause we couldn't stop people from writing case _ instead of else, but it would be easier to make PEP 8 say "prefer else over case _" if there was no additional cognitive dissonance over the difference in meaning conferred by the different indentation levels.

@gvanrossum
Copy link
Owner Author

Greg Ewing just made a good observation. The flat indentation scheme looks like a mistake. I think that's as good an argument against it as we're going to get, and it satisfies me.

@Tobias-Kohn
Copy link
Collaborator

In short: I think the identation we proposed in the PEP is perfectly fine and reasonable, and, to be honest, I really do not see why people are so afraid of it, or why this is such a big deal.

On the other hand, I like Guido's explanation with the two different approaches to how the pattern matching works as a multi-condition statement. It also makes it clear that we are really discussing the aspect of branching and not of actual pattern matching itself.

Anyway, some of the arguments like that there is no other similar structure in Python are simply not true. If you define a class, you end up indenting the actual code that is executed twice, too (yes, I am fully aware of the syntax and semantics of class definitions and that you can do some wild stuff). I have not been around back then, but I wonder whether there was a similar discussion about whether you should rather write it as:

class C:
def __init__(self):
    ...
def foo(self):
    ...

You might argue that that's a completely different case, although, actually, it is not!

The match statement evaluates an expression and introduces a "scope" where the value of the expression is valid and defined. It is very similar in that regard to a with block, with the difference being that in a with block you explicitly assign the return value of the context manager to a variable using as. The methods inside a class share the instance as something like an implicit value (Python as one of the only languages makes actually makes it explicit through the self parameter, of course). Moreover, the case arms themselves are in principle and function similar to functions: the patterns in their basic form are extremely close to a function's parameter list (something that has been pointed out on the dev-mailing list).

The one thing that really is different is that case is the only statement allowed inside a match block and it is not a statement that can live outside of it. This is a point that I had brought up in my initial article on pattern matching: should we allow other statements to appear in a match block, and if so, with what kind of semantics. Or, alternatively, could a case live on its own outside a match (I believe my answer to the second question was to make a case outside a match block the one-off variant proposed by Ivan). But even today, there are some statements such as return or nonlocal that can only really live inside a certain scope and do not make much sense otherwise.

One of the reason I brought up the class definition is of course, because I actually happen to think of case clauses as the "big sister" of lambda-expressions, if you will. The dispatch semantics of which case clause is eventually chosen feels to me extremely similar to how a specific function or method is chosen in a language with method overloading. Of course, this is not true on the level of implementation, and as Guido has pointed out, is completely isomorphic to the actual runtime semantics.

Long story short: I am also probably one of the guys who do not think of this pattern matching statement as an enhanced if-elif-else chain, but rather as a set of quasi-functions with different parameter lists, from which the most appropriate one is chosen to fit the arguments.

@Tobias-Kohn
Copy link
Collaborator

Tobias-Kohn commented Jul 12, 2020

Just a minor thing, but since the teaching aspect has already been brought up a couple of times: to my experience, teaching the semantics of if-elif-else chains is not quite that easy for novice programmers. There are a couple of hurdles, such as why the first case has an if when all the following ones use elif instead, and why other cases are skipped, although Python is supposed to go through the chain one by one, etc.

I honestly believe that the idea of "Python chooses the most appropriate case from the set" is easier to understand for a novice than some form of chain—including the jumping out of the match block once a case has been executed, rather than the notion of skipping the rest. Obviously, I do not have hard evidence for this, though.

@gvanrossum
Copy link
Owner Author

Thank you. I think we can leave the indentation issue behind and also the else conundrum. We don't need to add anything to the PEP.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants