patma
patma copied to clipboard
'continue' and 'break' in case blocks
@brandtbucher proposed to support continue in case blocks, with the semantics of skipping forward to the next case. This could be used instead of guards (#3). E.g.
match [randint(1, 6), randint(1, 6)]:
case [a, b]:
if a != b: continue
print("Pair:", a)
...
If we were to support this we could also support break, which would exit the match statement.
Note that continue could also be used to emulate C's "fall-through" behavior (which should definitely not be the default):
match x:
case Foo(a, b): continue
case Bar(a, b): print("Either a Foo or a Bar", a, b)
continue makes more sense to me as "continue trying more matches". Blindly jumping into the next match block causes all sorts of problems with missing variable extractions, etc. Besides, it's nothing that couldn't already be done with union patterns.
I also like using break this way, and the two are a natural pair. It seems very symmetric that there's an implicit break at the end of a block, similar to an implicit return at the end of a function.
It is also ironically echoing C's use of break in switch statements. :-)
There is one downside to giving continue and break in match statement special meaning: there is a common code pattern where one loops over some values and has an if ... elif ... else on the value. There are two problems if some of the branches has continue or break statements:
- When one refactor such
if ... elif ... elseinto a match statement, thosecontinueandbreaksuddenly change meaning (in a somewhat subtle way). - Even when one is well aware about semantics of
continueandbreakin match statements it will be awkward to achieve the desired semantics in a loop.
Thinking about my own experience, I wanted to break out of an if ... elif ... else chain quite rarely, while I wanted to break or continue a loop from such chain quite often. Also I think that most use cases for proposed continue semantics can be achieved using guards or assignment expression or | patterns.
Together, I think this may be a strong argument in favor of making continue and break target the enclosing loop rather than the match statement itself.
I agree.
One aspect of break and continue that I really do not like is that it forces the individual cases into an order. Although this is clearly beyond the scope of what we are currently doing in Python, most languages with pattern matching compile it down to something like a finite state machine. That is, a simple example like this:
match x:
case foo(2): ...
case foo(3): ...
case bar(a): ...
is actually compiled down to hierarchical code like this:
if isinstance(x, foo):
if foo.arg == 2: ...
elif foo.arg == 3: ...
elif isinstance(x, bar):
....
Introducing break and continue as operators on the match statement would make such optimisations much harder. Yes, I know that this would be nearly impossible to do with our proposal in Python, but I still feel that break and continue do not fit the overall notion of pattern matching.
Anyway, I also fully agree with that match statements are more likely to contain a break or continue to affect a surrounding loop, as Ivan noted. In fact, I first considered using a for loop for my own implementation of case as it seems to be almost ideally suited for that purpose (the iterator can return either zero or one element, which would be a tuple with the values for variables to bind). However, the fact that such a for loop would capture any breaks and continues made me look for a different way and abandon that idea.
So, long story short, I would not include break and continue as part of pattern matching.
@brandtbucher -- any final words about this? Otherwise I propose to label this as "rejected".
Nope, great points have been made. I agree that the drawbacks outweigh the benefits.
Let's keep rejected issues open though. I like to have the full discussion visible.
Agreed - a rejected issue is not 'closed' because there is still work to be done - writing up the reason why it was rejected.
(If an issue had no impact at all on the PEP, then I suppose theoretically we could close it.)