[Python-ideas] x=(yield from) confusion [was:Yet another alternative name for yield-from]
Jacob Holm
jh at improva.dk
Tue Apr 7 04:59:31 CEST 2009
Greg Ewing wrote:
> Jacob Holm wrote:
>
>> No, in the coroutine pattern it absolutely should not. The first
>> value yielded by the generator of every coroutine is None and should
>> be thrown away.
>
> That only applies to the *top level* of a coroutine. If
> you factor some code out of a coroutine and call it using
> yield-from, the first value yielded by the factored-out
> code is needed and mustn't be thrown away.
One major reason for factoring something out of a coroutine would be if
the factored-out code was independently useful as a coroutine. But I
cannot actually *make* it a coroutine if I want to call it using
yield-from because it is not always at the "top level".
>
> So I stand by what I said before. If you're using such
> a decorator, you only apply it to the top level generator
> of the coroutine, and you don't call the top level
> using yield-from.
>
So one @coroutine can't call another using yield-from. Why shouldn't it
be possible? All we need is a way to avoid the first next() call and
substitute some other value.
Here is a silly example of two coroutines calling each other using one
of the syntax-based ideas I have for handling this. (I don't care about
the actual syntax, just about the ability to do this)
@coroutine
def avg2():
a = yield
b = yield
return (a+b)/2
@coroutine
def avg_diff():
a = yield from avg2() start None # "start EXPR" means use EXPR for first value to yield instead of next()
b = yield from avg2() start a # "start EXPR" means use EXPR for first value to yield instead of next()
yield b
return a-b
a = avg2()
a.send(41)
a.send(43) # raises StopIteration(42)
d = avg_diff()
d.send(1.0)
d.send(2.0) # returns from first yield-from, yields 1.5 as part of starting second yield-from
d.send(3.0)
d.send(4.0) # returns from second yield-from. yields 3.5
d.next() # returns from avg_diff. raises StopIteration(-2.0)
The important things to note here are that both avg2 and avg_diff are
independently useful coroutines (yeah ok, not that useful), and that the
"natural" value to yield from the "d.send(2.0)" line does not come from
calling next() on the subgenerator, but rather from the outer generator.
I don't think there is any way to achieve this without some way of
substituting the initial next() call in yield-from.
Regards
- Jacob
More information about the Python-ideas
mailing list