[Python-ideas] Cofunctions - Getting away from the iterator protocol
Ron Adam
ron3200 at gmail.com
Tue Nov 1 06:10:46 CET 2011
On Mon, 2011-10-31 at 23:58 -0500, Ron Adam wrote:
> On Tue, 2011-11-01 at 11:14 +1000, Nick Coghlan wrote:
> > On Tue, Nov 1, 2011 at 10:22 AM, Ron Adam <ron3200 at gmail.com> wrote:
> > > On Tue, 2011-11-01 at 10:06 +1300, Greg Ewing wrote:
> > >> Ron Adam wrote:
> > >> > If we put some strict requirements on the idea.
> > >> >
> > >> > 1. Only have a *SINGLE* exception type as being resumable.
> > >> >
> > >> > 2. That exception should *NEVER* occur naturally.
> > >> >
> > >> > 3. Only allow continuing after it's *EXPLICITLY RAISED* by a
> > >> > raised statement.
> > >> >
> > >> > All of the problem issues go away with those requirements in place, and
> > >> > you only have the issue of how to actually write the patch. Earlier
> > >> > discussions indicated, it might not be that hard to do.
> > >>
> > >> I'm not familiar with these earlier discussions. Did they go
> > >> as far as sketching a feasible implementation? It's all very
> > >> well to propose things like this, but the devil is very much
> > >> in the details.
> > >
> > > Yeah, there isn't very much about the details, but I think it is worth
> > > looking into as it would pretty much does exactly what is needed. (IMHO)
> >
> > It gave me another thought on an existing utility worth exploring in
> > this context: pdb's post-mortem capabilities.
> >
> > Now, those *don't* implement coroutines (when you do a postmortem, you
> > end up in an emulation of the eval loop, not the eval loop itself).
> > However, that exception instance *does* contain the full frame stack,
> > all the way down to where the exception was thrown. Figuring out what
> > hooks you would need in the core eval loop in order to reinstate an
> > exception's frame stack as the "real" frame stack might be an
> > interesting exercise.
>
> Poking around a bit, it looks like 'raise' does most of the work and the
> exception is just an envelope for what ever 'raise' puts in it. Is that
> right?
>
>
>
> I'd like to be able to make this work.
>
> class Suspend:
> def __init__(self, source):
> self.source = source
> self.suspend = True
>
> def __next__(self):
> nonlocal self.suspend
> if self.suspend:
> self.suspend = False
> raise SuspendException
> self.suspend = True
> return next(self.source)
LOL... Need to recheck my cut and copy between edits.
Remove the nonlocal self.suspend. It was just to see what if anything
acted different and I forgot to remove it.
> There are two issues with it...
>
> The "self.suspend = False" doesn't seem to work. The __next__ seems to
> get it's own copies of the attributes at the time the generator is
> created.
Ok, the self.suspend reference does work as it should. I was just not
putting my print statement in the right place. Time to call it a night.
The rest is ok.
Cheers,
Ron
> And after the SuspendException is raised, a StopIteratoion is issued on
> the next next() call. The StopIteration is from the whole chain. The
> only reason the scheduler doesn't stop is it catches the
> Suspendexception.
>
> I want to be able to stick something like this in the generator chained
> pipe example below.
>
> Cheers,
> Ron
>
>
>
> *This is broken down into finer steps than you would normally do in
> order to test how it behaves.
>
> """
> Basic scheduler test -- co-pipes version
> """
> from co_pipes import *
>
> def Person(args):
> name, count = args
> p = Producer(lambda:name) # call function each time
> p = Limit(p, count) # stop after count yields.
> p = Enumerate(p) # -> (n, data)
> #p = Suspend(p) # suspend doesn't work.
> p = Apply(p, "{0[0]}: {0[1]} ".format)
> p = Apply(p, print) # consumer
> for _ in p:
> yield # pull data from here.
>
> def main(data):
> p = Source(data) # take an iterable
> p = Apply(p, Person) # apply a callable to data
> p = Collect(p) # collect items in a list
> p = Scheduler(p) # take a list of generators.
> next(p) # start the scheduler.
>
> if __name__ == "__main__":
> data = [("John", 2), ("Micheal", 3), ("Terry", 4)]
> main(data)
>
>
> Prints...
>
> 1: John
> 1: Micheal
> 1: Terry
> 2: John
> 2: Micheal
> 2: Terry
> 3: Micheal
> 3: Terry
> 4: Terry
>
>
>
>
More information about the Python-ideas
mailing list