[Python-Dev] Proposal for 2.5: Returning values from PEP 342 enhanced generators
PEP 255 ("Simple Generators") closes with: > Q. Then why not allow an expression on "return" too? > > A. Perhaps we will someday. In Icon, "return expr" means both "I'm >done", and "but I have one final useful value to return too, and >this is it". At the start, and in the absence of compelling uses >for "return expr", it's simply cleaner to use "yield" exclusively >for delivering values. Now that Python 2.5 gained enhanced generators (multitudes rejoice!), i think there is a compelling use for valued return statements in cooperative multitasking code, of the kind: def foo(): Data = yield Client.read() [...] MoreData = yield Client.read() [...] return FinalResult def bar(): Result = yield foo() For generators written in this style, "yield" means "suspend execution of the current call until the requested result/resource can be provided", and "return" regains its full conventional meaning of "terminate the current call with a given result". The simplest / most straightforward implementation would be for "return Foo" to translate to "raise StopIteration, Foo". This is consistent with "return" translating to "raise StopIteration", and does not break any existing generator code. (Another way to think about this change is that if a plain StopIteration means "the iterator terminated", then a valued StopIteration, by extension, means "the iterator terminated with the given value".) Motivation by real-world example: One system that could benefit from this change is Christopher Armstrong's defgen.py[1] for Twisted, which he recently reincarnated (as newdefgen.py) to use enhanced generators. The resulting code is much cleaner than before, and closer to the conventional synchronous style of writing. [1] the saga of which is summarized here: http://radix.twistedmatrix.com/archives/000114.html However, because enhanced generators have no way to differentiate their intermediate results from their "real" result, the current solution is a somewhat confusing compromise: the last value yielded by the generator implicitly becomes the result returned by the call. Thus, to return something, in general, requires the idiom "yield Foo; return". If valued returns are allowed, this would become "return Foo" (and the code implementing defgen itself would probably end up simpler, as well). ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
[Python-Dev] Proposal for 2.5: Returning values from PEP 342 enhanced generators
PEP 255 ("Simple Generators") closes with: > Q. Then why not allow an expression on "return" too? > > A. Perhaps we will someday. In Icon, "return expr" means both "I'm >done", and "but I have one final useful value to return too, and >this is it". At the start, and in the absence of compelling uses >for "return expr", it's simply cleaner to use "yield" exclusively >for delivering values. Now that Python 2.5 gained enhanced generators (multitudes rejoice!), i think there is a compelling use for valued return statements in cooperative multitasking code, of the kind: def foo(): Data = yield Client.read() [...] MoreData = yield Client.read() [...] return FinalResult def bar(): Result = yield foo() For generators written in this style, "yield" means "suspend execution of the current call until the requested result/resource can be provided", and "return" regains its full conventional meaning of "terminate the current call with a given result". The simplest / most straightforward implementation would be for "return Foo" to translate to "raise StopIteration, Foo". This is consistent with "return" translating to "raise StopIteration", and does not break any existing generator code. (Another way to think about this change is that if a plain StopIteration means "the iterator terminated", then a valued StopIteration, by extension, means "the iterator terminated with the given value".) Motivation by real-world example: One system that could benefit from this change is Christopher Armstrong's defgen.py[1] for Twisted, which he recently reincarnated (as newdefgen.py) to use enhanced generators. The resulting code is much cleaner than before, and closer to the conventional synchronous style of writing. [1] the saga of which is summarized here: http://radix.twistedmatrix.com/archives/000114.html However, because enhanced generators have no way to differentiate their intermediate results from their "real" result, the current solution is a somewhat confusing compromise: the last value yielded by the generator implicitly becomes the result returned by the call. Thus, to return something, in general, requires the idiom "yield Foo; return". If valued returns are allowed, this would become "return Foo" (and the code implementing defgen itself would probably end up simpler, as well). ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 342 suggestion: start(), __call__() and unwind_call() methods
Nick Coghlan wrote: > Phillip J. Eby wrote: >> Nick Coghlan wrote: > [...] > >> Last, but far from least, as far as I can tell you can implement all of >> these semantics using PEP 342 as it sits. That is, it's very simple to >> make decorators or classes that add those semantics. I don't see >> anything that requires them to be part of Python. > > > Yeah, I've now realised that you can do all of this more simply by doing it > directly in the scheduler using StopIteration to indicate when the coroutine > is done, and using yield to indicate "I'm not done yet". Earlier this week, i proposed legalizing "return Result" inside a generator, and making it act like "raise StopIteration( Result )", for exactly this reason. IMHO, this is an elegant and straightforward extension of the current semantics of returns inside generators, and is the final step toward making generator-based concurrent tasks[1] look just like the equivalent synchronous code (with the only difference, more-or-less, being the need for appropriate "yield" keywords, and a task runner/scheduler loop). This change would make a huge difference to the practical usability of these generator-based tasks. I think they're much less likely to catch on if you have to write "raise StopIteration( Result )" (or "_return( Result )") all the time. [1] a.k.a. coroutines, which i don't think is an accurate name, anymore. ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com