On Sat, Oct 30, 2010 at 4:42 PM, Ron Adam <rrr at ronadam.com> wrote:
> Ok, after thinking about this for a while, I think the "yield from" would be
> too limited if it could only be used for consumers that must run until the
> end. That rules out a whole lot of pipes, filters and other things that
> consume-some, emit-some, consume-some_more, and emit-some_more.
Indeed, the "stop-in-the-middle" aspect is tricky, but is the crux of
what we're struggling with here.
> I think I figured out something that may be more flexible and insn't too
> complicated.
Basically a way to use yield from, while declaring how to force the
end of iteration? Interesting idea.
However, I think sentinel values are likely a better way to handle
this in a pure PEP 380 context.
> Here's an example.
Modifying this example to use sentinel values rather than throwing in
exceptions actually makes it all fairly straightforward in a PEP 380
context. So maybe the moral of this whole thread is really "sentinel
values good, sentinel exceptions bad".
# Helper function to finish off a generator by sending a sentinel value
def finish(g, sentinel=None):
try:
g.send(sentinel)
except StopIteration as ex:
return ex.value
def gtally(end_tally=None):
# Tallies numbers until sentinel is passed in
count = tally = 0
value = object()
while 1:
value = yield
if value is end_tally:
return count, tally
count += 1
tally += value
def gaverage(end_avg=None):
count, tally = (yield from gtally(end_avg))
return tally / count
def main():
g = gaverage()
next(g)
for x in range(100):
g.send(x)
return finish(g)
Even more complex cases, like my sum-of-averages example (or any
equivalent multi-level construct) can be implemented without too much
hassle, so long as "finish current action" and "start next action" are
implemented as two separate steps so the outer layer has a chance to
communicate with the outside world before diving into the inner layer.
I think we've thrashed this out enough that I, for one, want to see
how PEP 380 peforms in the wild as it currently stands before we start
tinkering any further.
Cheers,
Nick.
--
Nick Coghlan | ncoghlan at gmail.com | Brisbane, Australia