[Python-ideas] yield-from and @coroutine decorator [was:x=(yield from) confusion]

Jacob Holm jh at improva.dk
Sat Apr 4 01:34:16 CEST 2009

Nick Coghlan wrote:
> Jacob Holm wrote:
>> We should probably drop that particular bikeshed discussion until we
>> actually know the details of what the construct should do, esp in the
>> context of close(). I am starting to lose track of all the different
>> possible versions.
> Note that the syntax for returning values from generators is largely
> independent of the semantics. Guido has pointed out that disallowing the
> naive "return EXPR" in generators is an important learning tool for
> inexperienced generator users, and I think he's right.

I agree that a separate syntax for returning a value from a 
generator/coroutine is propably a good idea.  (I am still not convinced 
we need a separate exception for it, but that is a separate 
discussion).  I even think it would be a good idea to deprecate the use 
of the normal "return" in generators, but that is probably not going to 

> "return finally" reads pretty well and doesn't add a new keyword, while
> still allowing generator return values to be written easily. I haven't
> seen other suggestions I particularly like, so I figured I'd run with
> that one for the revised example :)

You can call it whatever you want, as long as it works predictably for 
the use cases we are finding.

>> Now for my problem. The original averager example was inspired by the
>> tutorial http://dabeaz.com/coroutines/ that Guido pointed to. (Great
>> stuff, btw). One pattern that is recommended by the tutorial and used
>> throughout is to decorate all coroutines with a decorator like:
>> def coroutine(func):
>>    def start(*args,**kwargs):
>>        cr = func(*args,**kwargs)
>>        cr.next()
>>        return cr
>>    return start
>> The idea is that it saves you from the initial next() call used to start
>> the coroutine. The problem is that you cannot use such a decorated
>> coroutine in any flavor of the yield-from expression we have considered
>> so far, because the yield-from will start out by doing an *additional*
>> next call and yield that value.
>> I have a few vague ideas of how we might change "yield from" to support
>> this, but nothing concrete enough to put here. Is this a problem we
>> should try to fix, and if so, how?
> Hmm, that's a tricky one. It sounds like it is definitely an issue the
> PEP needs to discuss, but I don't currently have an opinion as to what
> it should say.

Here is one possible fix, never mind the syntax.  We could change the 
yield from expression from the current:

  RESULT = yield from EXPR

by adding an extra form, possibly one of:

  RESULT = yield from EXPR with STARTEXPR
  RESULT = yield from EXPR as NAME starting with STARTEXPR(NAME)

And letting STARTEXPR if given take the place of the initial _i.next() 
in the expansion(s).  The point is we need to yield *something* first, 
before rerouting all send(), next() and throw() calls to the subiterator.

>> not-trying-to-be-difficult-ly yours
> We have a long way to go before we even come close to consuming as many
> pixels as PEP 308 or PEP 343 - a fact for which Greg is probably grateful ;)
Him and everybody else I would think.  But AFAICT we are not even close 
to finished, so we may get there yet.

- Jacob

More information about the Python-ideas mailing list