I don't get why they discarded<p><i>for/while... as label1:<p>__for/while... as label2:<p>___break label1</i><p>suggestion. It actually seems a good enough idea to implement that. And it's rather concise. I often need to break deep inner loops to outermost and doing it with flags is... strange.
> But the arguments given in support of the feature were generally fairly weak; they often used arbitrary, "made up" examples that demonstrated a place where multi-level break could be used, but were not particularly compelling.<p>> To make this proposal convincing, we need a <i>realistic</i> example of an algorithm that uses it, and that example needs to be <i>significantly</i> more readable and maintainable than the refactorings into functions, or the use of try…except (also a localised goto).<p>How about this:<p><pre><code> found = None
for r, row in enumerate(table.rows):
for c, cell in enumerate(row):
if search_query.matches(cell.value):
found = (r, c)
break 2
logger.log("Found cell: {}".format(found))
return found</code></pre>
I think it boils down to "early exit" v.s. "single return" style. More than likely, the average programmer will pick the style they've been taught at school or whichever was preached more.<p>I think early exit constructs improve readability and python already offers a lot of syntax open to abuse at this point. (things you can write with nested list/dict comprehensions with if conditions/expressions scattered..)
The first thing that came to mind was either for/else, try/except, or refactoring out to a function which were all mentioned in the article. This solves the problem in all cases except a multi-level continue as it was called, and the solution by Python Millionaire was essentially goto labels. The reason high level programming languages moved away from goto labels is because they create spaghetti code. Goto labels were before for and while loops and are not necessary now, but this is a shallow answer because goto labels do work.<p>To dig deeper into why goto labels are bad and the alternative, what goto labels allow you to do is to create a state machine in procedural code. The more explicit way to do this is to create a dictionary object that tracks the state and a while loop with state-based logic that includes a halting condition. But according to Python Millionaire this would not be “Pythonic” which is basically just a blanket term for saying it is built into the language and therefore designed to be simple and easy to read. However, I would argue that goto statements are inherently un-Pythonic because they encourage spaghetti code. I don’t see how for/else or try/except is not Pythonic, but also I don’t see the aversion to refactoring to separate function which is the accepted cross-language way to refactor and simplify code. It even lets you write a built-in comment for what the function does, the function name. That being said, an easy way to determine if the function failed is to either throw and exception or simply return a result like True/False which would determine whether to break out of the parent loop.
Personally I like very much the solution proposed at the end of comments:<p><a href="https://lwn.net/Articles/907510/" rel="nofollow">https://lwn.net/Articles/907510/</a><p>With something like:
For loop... As my_loop:
my_loop.continue()
Python has coroutines (in the original sense), so one can implement almost Break-break. For example, it's easy to implement an object so that this will work as expected:<p><pre><code> from easytowritelibrary import LoopManager
lm = LoopManager()
for x in lm(a1):
for y in lm(a2):
if cond:
lm.break_(2); break
block()
</code></pre>
It can support stuff like:<p><pre><code> for x in lm(a1, "a1"):
for y in lm(a2, "a2"):
if cond1:
lm.break_("a1"); break
if cond2:
lm.continue_("a1"); break
block()
</code></pre>
It can't handle "for-else" correctly, but maybe that's OK.
I argue for a "break" with a number that indicates how many loops you want to break out of. I have this in my programming language <a href="https://easylang.online" rel="nofollow">https://easylang.online</a>. Each "break" needs the number, so also a "break 1".<p><pre><code> for i = 1 to 50
for j = 1 to 50
if i * i + j * j * j = 80036
break 2
end
end
end
print i & " " & j</code></pre>
Walrus operator? In. F string interpolation? In. Pattern matching? Hacked in.<p>Genuinely useful feature that is awkward to emulate? Nah.<p>Let's face it, everyone writes a double or triple nested for loop every now and then.
It's more tedious in C derivatives, where loops and switches share the break keyword. Where that isn't the case, it's much harder to justify multi-level break. Refactor to a function and return instead.
have always wanted `break break` syntax for this kind of thing<p><pre><code> for x in a1:
for y in a2:
if test(y):
break break # break both outer loops
</code></pre>
in general, I wonder if there's a class of 'tree-like' control structures which can break multiple levels under certain circumstances<p>an application might be scope management parsing -- I tried to build something like this a while ago, not clear that it's better than parser-generators but it's certainly different
Common Lisp has a system of Conditions and Restarts which can do this and more.<p>The link below describes an example of handling errors which arise when reading a collection of files line by line.<p><a href="https://gigamonkeys.com/book/beyond-exception-handling-conditions-and-restarts.html" rel="nofollow">https://gigamonkeys.com/book/beyond-exception-handling-condi...</a>