
Jacob Holm wrote:
After doing "yield from R" in generator A, you can go ahead and do "yield from R" in generator B as well. If R is also using "yield from" you will have the following situation:
A \ R --- (whatever R is waiting for) / B
Unless you're doing something extremely unusual, this situation wouldn't arise. The yield-from statement is intended to run the iterator to exhaustion, and normally you'd create a fresh iterator for each yield-from that you want to do. So A and B would really be yielding from different iterators, even if they were both iterating over the same underlying object. If you did try to share iterators between yield-froms like that, you would have to arrange things so that at least all but one of them broke out of the loop early, otherwise something is going to get an exception due to trying to resume an exhausted iterator. But in any case, I think you can still model this as two separate stacks, with R appearing in both stacks: [A, R] and [B, R]. Whichever one of them finishes yielding from R first pops it from its stack, and when the other one tries to resume R it gets an exception. Either that or it breaks out of its yield-from early and discards its version of R.
As long as that scenario is possible I can construct an example where treating it as a simple stack will either do the wrong thing, or do the right thing but slower than a standard "for v in it: yield v".
That depends on what you think the "right thing" is. If you think that somehow A needs to notice that B has finished yielding from R and gracefully stop doing so itself, then that's not something I intended and it's not the way the current prototype implementation would behave. So IMO you're worrying about a problem that doesn't exist. -- Greg