unintuitive for-loop behavior

Gregory Ewing greg.ewing at canterbury.ac.nz
Fri Sep 30 20:46:16 EDT 2016


Steve D'Aprano wrote:
> Giving for-loops their own namespace is a grossly unintuitive and a very
> weird thing to do.
> 
> It would be terribly inconvenient and surprising for if...else blocks to be
> separate namespaces:

There's an important difference between a for-loop and an
if-statement that's relevant here: a for-loop binds a name,
whereas an if-statement doesn't.

Whenever there's binding going on, it's necessary to decide
whether it should be creating a new binding or updating an
existing one.

This is actually a *different* issue from one of scope.
List comprehensions were changed so that the loop variable
lives in a different scope from the containing function.
However, they still have the same unintuitive behaviour
with regard to capture of the loop variable by a lambda.

 >> l = [lambda: i for i in range(3)]
 >>> for f in l: print(f())
...
2
2
2

Most people consider *this* behaviour to be far weirder
than anything that would result from giving for-loop
variables their own scope.

Even if you don't think it's weird, it's hard to argue
that it's *useful* in any significant number of cases.

> To me, "make for-loops be their own scope" sounds like a joke feature out of
> joke languages like INTERCAL.

Which is a straw man, since that's not actually what we're
talking about doing. It's neither necessary nor sufficient
to solve the problem.

What *is* necessary and sufficient is to make each iteration
of the for-loop create a new binding of the loop variable
(and not any other variable!).

> I'm not aware of any sensible language that
> does anything like this.

Scheme and Ruby come to mind as examples of languages in
which the equivalent of a for-loop results in each iteration
getting a new binding of the control variable. Although
you could argue that these languages are not "sensible". :-)

-- 
Greg



More information about the Python-list mailing list