[Python-Dev] Lexical scoping in Python 3k

Guido van Rossum guido at python.org
Mon Jul 3 17:45:49 CEST 2006


On 7/3/06, Andrew Koenig <ark at acm.org> wrote:
> > I don't think "trivial" is the right word to use here,
> > since it implies something that's of so little importance
> > that it can be ignored. But the simple cases are precisely
> > the ones where this wart hurts the most, so we can't
> > ignore them.
>
> I'd like to inject an example that might help make this discussion more
> concrete.
>
> Consider the following function:
>
>         def for_each(seq, f):
>                 for i in seq:
>                         f(i)
>
> I'm sure I've seen more than one instance of someone on comp.lang.python
> trying to do the equivalent of using a function such as this one to compute
> the sum of the elements of a sequence as follows:
>
>         def sum(seq):
>                 result = 0
>                 def accum(i):
>                         result += i
>                 for_each(seq, accum)
>                 return result
>
> and wonder why it doesn't work.  Still odder, why it doesn't work and the
> following does:
>
>         def sum(seq):
>                 result = [0]
>                 def accum(i):
>                         result[0] += i
>                 for_each(seq, accum)
>                 return result[0]
>
> Transforming the first definition of sum above into the second may be
> trivial, but only if you've encountered the technique before.  Moreover, the
> first version of sum uses a technique that is more than 45 years old (!), as
> it was available to Algol 60 programmers.

Much though the Algol 60 tickles my nostalgia (it was my first
programming language!) I don't think that it's a particularly strong
argument. I like to think that we have better ways these days.

I think you need to come up with a better motivating example; the
above is particular un-idiomatic Python. It starts by defining a
higher-order function for_each that has little to offer over writing
an explicit for loop, and then uses this to motivate writing a simple
operation (result += i) as a function instead so that it fits in the
inconvenient for_each() API.

I understand that both for_each() and accum() are just examples of
more complicated functions, but I can't help thinking that the problem
here only occurs for very *simple* functions in the place of accum();
a more complicated form of accum would likely be a bound method of a
class instance which carries the state.

A better way to decompose these kinds of problems is probably by using
generators. The equivalent of for_each() would not take a function
parameter but *yield* the successive values instead of calling f()
with successive values; e.g.:

  def for_each(seq):
    for i in seq:
      yield i

Then the sum() function could be written like this:

  def sum(seq):
    result = 0
    for i in for_each(seq):
      result += i
    return result

-- 
--Guido van Rossum (home page: http://www.python.org/~guido/)


More information about the Python-Dev mailing list