[Python-Dev] Possible resolution of generator expression variable capture dilemma

Greg Ewing greg at cosc.canterbury.ac.nz
Wed Mar 24 20:43:15 EST 2004


"Anders J. Munch" <andersjm at dancontrol.dk>:

> A simple change to Tim's example:
> 
>      pipe = source
>      for p in predicates:
>          filter = p.filter
>          # add a filter over the current pipe, and call that the new pipe
>          pipe = e for e in pipe if filter(e)

I was afraid someone would say something like that. :-)

This is a good point. Clearly there are cases where you want
new-binding behaviour on something that is not a loop variable. But
equally there are cases where you definitely *don't* want it, and it
seems like a bad idea to have the compiler try to guess which is
which.

Once again, Scheme has the advantage here, because it's always
explicit about whether a new binding is being created or an existing
one changed. So perhaps what we want is an explicit way of creating a
new binding.  Maybe something like

  let <var> = <expr>

Using this, the augmented Tim example becomes

   pipe = source
   for p in predicates:
     let filter = p.filter
     let pipe = e for e in pipe if filter(e)

(By using 'let' on 'pipe' as well, this will work even if the
first iterator is not pre-computed, although pre-computing it
might still be desirable for other reasons to be debated
separately. If it is pre-computed, the second 'let' would not be
necessary in this example.)

Now, if we're being explicit about things, it would make sense to be
explicit about what happens to the loop variable as well.  I suggest

  for each <var> in <expr>:

as a new-binding version of the for loop. The original Tim
example is then

     pipe = source
     for each p in predicates:
         let pipe = e for e in pipe if p(e)

An objection to all this might be that it won't do anything to reduce
surprises, because you have to already be aware of the possibility of
surprises and put lets and eaches in the right places to avoid them.

But that's no worse than the way things are, where you have to be
aware of the possibility of surprises and do awkward things with
lambdas or extra function defs to avoid them.

The difference is that there will be a simple and straightforward way
of avoiding the surprises, rather than an obscure and hard to read
one.

Greg Ewing, Computer Science Dept, +--------------------------------------+
University of Canterbury,	   | A citizen of NewZealandCorp, a	  |
Christchurch, New Zealand	   | wholly-owned subsidiary of USA Inc.  |
greg at cosc.canterbury.ac.nz	   +--------------------------------------+



More information about the Python-Dev mailing list