On Mon, Dec 7, 2020 at 6:27 PM Daniel Moisset <[email protected]> wrote:

> For the likely rare situation where I'd want to do this rather than
> refactoring into a function, I might try with something like this without
> requiring changes to the language:
>
> from contextlib import contextmanager
>
> @contextmanager
> def breakable():
>     class Break(Exception): pass
>     def breaker(): raise Break
>     try:
>         yield breaker
>     except Break:
>         pass
>
> This allows defining a block that can be "aborted" (which can have a loop
> or any other statement block within); you abort it by calling the resulting
> value of the context manager. An example of use is available at
> https://gist.github.com/dmoisset/55f5916f9f339a143b6f3d155de8706e
>
>
I agree with the person who called this a brilliant solution. Here is the
code from the link for completeness:

for outer in range(5):
    with breakable() as brk:
        for middle in range(5):
            for inner in range(10):
                print(outer, middle, inner)
                if middle == 1 and inner == 5:
                    brk()
            print(f"end middle loop #{middle}")
    print(f"end outer loop #{outer}")
print("done")

Iterating on that idea a bit and taking advantage of the walrus, what if
syntax were created allowing us to remove the extra indentation level, and
also allowing us to contextualize any loop without having to employ the
with statement? I imagine is looking something like this:

for outer in range(5):
    @breakable
    for middle in loopX := range(5):
        for inner in range(10):
            print(outer, middle, inner)
            if middle == 1 and inner == 5:
                loopX.brk()
        print(f"end middle loop #{middle}")
    print(f"end outer loop #{outer}")
print("done")


Above, breakable will be some decorator that returns a context manager, and
the "loopX" loop happens in the context of that context manager (with the
name "loopX" assigned to the context object).

Here is some more detail about what I am imagining happening with this new
syntax:

   1. the name `loopX` is assigned to the iterable in the for statement, as
   usual
   2. the first time the for statement ` for middle in loopX := range(5):
   `  is interpreted/excuted, the presence of the decorator causes this to
   happen before iteration starts:

   loopX = breakable(loopX)
   with loopX as loopX:
       for middle in loopX := range(5):
           # the "loopX" loop is now executed within the loopX context

   3. the utility of this syntax would not be limited to the breaking of
   named loops. with this syntax in place, one could write any kind of context
   manager they want for contextualizing the execution of loops (both for
   loops and while loops).
   4. last note: if no name is supplied to the iterable object using the
   walrus, then applying the decorator to the loop would be a syntax error


What do you think?

---
Ricky.

"I've never met a Kentucky man who wasn't either thinking about going home
or actually going home." - Happy Chandler


<http://python.org/psf/codeofconduct/>
>
_______________________________________________
Python-ideas mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/[email protected]/message/BQCGXITAKOVG24KWYZB5CW7DUFFYM3AK/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to