[Python-ideas] x=(yield from) confusion [was:Yet another alternative name for yield-from]
jh at improva.dk
Mon Apr 6 15:41:27 CEST 2009
Greg Ewing wrote:
> Jacob Holm wrote:
>> The argument that we have no value to send before we have yielded is
>> wrong. The generator containing the "yield-from" could easily have a
>> value to send (or throw)
> No, Guido is right here. You *can't* send a value (other
> than None) into a generator that hasn't reached its first
> yield (try it and you'll get an exception). The first
> call has to be next().
The whole idea of the coroutine pattern is to replace this restriction
on the caller with a restriction about the first yield in the coroutine.
This would probably be a lot clearer if the coroutine decorator was
cr = func(*args,**kwargs)
v = cr.next()
if v is not None:
raise RuntimeError('first yield in coroutine was not None')
The first call *from user code* to a generator decorated with @coroutine
*can* be a send() or throw(), and in most cases probably should be.
>> and if iter(EXPR) returns a coroutine or a non-generator it could
>> easily be ready to accept it.
> If it's ready to accept a send, it must have already
> yielded a value, which has been lost, when it should have
> been yielded to the caller of the delegating generator.
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
>> Next issue is that the value returned by it.close() is thrown away by
> Since I don't believe that close() should be expected to
> return a useful value anyway, that's not a problem.
It is a problem in the sense that it is surprising behavior. If close()
doesn't return the value, it should at least raise some exception. I am
warming to the idea of reraising the StopIteration if it has a non-None
value. This matches Guidos suggestion for how to retrieve the value
after a yield-from that was thrown a GeneratorExit. If you insist it is
an error to return a value as response to GeneratorExit, raise
RuntimeError. But *please* don't just swallow the value.
More information about the Python-ideas