PEP 255: Simple Generators

Denys Duchier Denys.Duchier at ps.uni-sb.de
Wed Jun 20 12:05:40 EDT 2001


"Tim Peters" <tim.one at home.com> writes:

> [Denys Duchier]
> > The one thing that rubs me the wrong way with this proposal is that it
> > is not compositional.  Unless I misread the PEP, the entire generation
> > logic must be defined in a single function (because the `yield'
> > keyword must statically occur within the body of the generator
> > function).  This makes it impossible to use higher-order programming
> > to assemble complex generators from smaller blocks.
> 
> Since higher-order programming is an aberration (meaning
> statistically rare) in idiomatic Python, a specific example would
> help.

Think for example of a tree traversal algorithm that is parametrized
by a procedure to be applied to each node.  My reading of the PEP does
not allow a procedure to be passed in that `yields' the node.

While possibly aberrant, let me suggest a higher-order programming
approach that would not even require a new keyword but merely a new
primitive which I'll call `generator'.  This primitive takes a unary
procedure as argument and returns an iterator.  The unary procedure
takes itself a `yield' procedure as argument.  Here is the fib example
of the PEP written with my proposal:

	def fib(yield):
	  a, b = 0, 1
	  while 1:
	    yield(b)
	    a, b = b, a+b
	
	g=generator(fib)

It's straightforward (in an implementation) to check that the yield
procedure which is invoked actually corresponds to the generator that
is currently executing.  If that's not the case, an exception should
be raised.

This proposal has the advantage that the boundary of the generator is
fixed late, namely at the time the `generator' primitive is invoked.
It also support full compositionality.

>  If, e.g., you want to
> build a generator that delivers the results from generators g and h
> alternately, it's easy (although I personally don't want to <wink>):
> 
> def zipgen(g, h):
>     giter = g()
>     hiter = h()
>     while 1:
>         yield giter.next()
>         yield hiter.next()

which I would write as follows:

def zipgen(g,h):
  def result(yield):
    g(yield)
    h(yield)
  return result

Cheers,

-- 
Dr. Denys Duchier			Denys.Duchier at ps.uni-sb.de
Forschungsbereich Programmiersysteme	(Programming Systems Lab)
Universitaet des Saarlandes, Geb. 45	http://www.ps.uni-sb.de/~duchier
Postfach 15 11 50			Phone: +49 681 302 5618
66041 Saarbruecken, Germany		Fax:   +49 681 302 5615



More information about the Python-list mailing list