I wanna propose making generators even weirder!

so, extended continue is an oldie: https://www.python.org/dev/peps/pep-0342/#the-extended-continue-statement

it'd allow one to turn:

    yield from foo

into:

    for bar in foo:
        continue (yield bar)

but what's this extended for-else? well, currently you have for-else:

    for x, y, z in zip(a, b, c):
        ...
    else:
        pass

and this works. you get the stuff from the iterators, and if you break the loop, the else doesn't run. the else basically behaves like "except StopIteration:"...

so I propose an extended for-else, that behaves like "except StopIteration as foo:". that is, assuming we could get a zip() that returns partial results in the StopIteration (see other threads), we could do:

    for x, y, z in zip(a, b, c):
        do_stuff_with(x, y, z)
    else as partial_xy:
        if len(partial_xy) == 0:
            x = dummy
            try:
                y = next(b)
            except StopIteration: y = dummy
            try:
                z = next(c)
            except StopIteration: z = dummy
            if (x, y, z) != (dummy, dummy dummy):
                do_stuff_with(x, y, z)
        if len(partial_xy) == 1:
            x, = partial_xy
            y = dummy
            try:
                z = next(c)
            except StopIteration: z = dummy
            do_stuff_with(x, y, z)
        if len(partial_xy) == 2:
            x, y = partial_xy
            z = dummy
            do_stuff_with(x, y, z)

(this example is better served by zip_longest. however, it's nevertheless a good way to demonstrate functionality, thanks to zip_longest's (and zip's) trivial/easy to understand behaviour.)

this would enable one to turn:

    return yield from foo

into:

    for bar in foo:
        continue (yield bar)
    else as baz:
        return baz

allowing one to pick apart and modify the yielded and sent parts, while still getting access to the return values.

currently if you have an arbitrary generator, you can't modify the yielded values without breaking send or return. in fact you can either pass-through yield and send and collect the return, or modify yield and forget about send and the return, or use very ugly syntax that makes everything look lower-level than it should, to be able to pick apart everything:

    try:
        bar = next(foo)
    except StopIteration as exc:
        baz = exc.value
    else:
        while True:
            try:
                bar = foo.send((yield bar))
            except StopIteration as exc:
                baz = exc.value
                break
    return baz

(this is exactly equivalent (if I didn't overlook anything) to the previous endearingly simple loop with extended for-else and extended continue)
_______________________________________________
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/4NZXWPOCV6CSM3CBIN4UDQGRWCVENCTY/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to