
Jacob Holm wrote:
try: _v = yield _u except Exception, _e: if hasattr(_i, 'throw'): _i.throw(_e)
Shouldn't this be "_u = _i.throw(e)" instead?
Yes, I think possibly it should... but I need to wait until my brain stops hurting from thinking about all this before I'll know for certain... I'm no longer sure that the implementation I'm working on can be exactly described in terms of any Python expansion, anyway. One problem is that if the generator gets None from a yield, it has no way of knowing whether it came from a next() or a send(None), so it doesn't know which method to call on the subiterator. The best that it could do is if _v is None: _u = _i.next() else: _u = _i.send(_v) but I would have to modify my implementation as it currently stands to make it work like that. This may be the right thing to do, as it would bring things into line with the advertised equivalence of next() and send(None), and you would still get an exception if you tried to send something non-None to an object without a send() method.
I strongly suspect that the lower bound for this problem is O(logn/loglogn) per operation, and I can see a number of ways to do it in O(logn) time.
Before you bust too many neurons on O() calculations, be aware that the constant factors are important here. I'm relying on traversing a delegation chain using C calls taking negligible time compared to doing it in Python, so that it can be treated as a constant-time operation for all practical purposes regardless of the length of the chain. Testing will reveal whether this turns out to be true in real life... -- Greg