unintuitive for-loop behavior

Rustom Mody rustompmody at gmail.com
Fri Sep 30 23:44:53 EDT 2016


For the most part you've taken the words out of my mouth!
Some more details...

On Saturday, October 1, 2016 at 6:16:32 AM UTC+5:30, Gregory Ewing wrote:
> 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!).


Yes one basic problem with comprehensions in python is that they are 
defined by assignment not binding to the comprehension 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". :-)

Python copied comprehensions from haskell and copied them wrong

Here are all the things (that I can think of) that are wrong:
1. Scope leakage from inside to outside the comprehension
2. Scope leakage from one value to the next
3. The name 'for' misleadingly associates for-loops and comprehensions
4. The for-loop based implementation strategy made into definitional semantics
5. The absence of simple binding inside comprehensions:
   [f(newvar) for v in l newvar = rhs]

1 was considered sufficiently important to make a breaking change from python2 to 3
2 is what causes the lambda gotcha
3 is what makes noobs to take longer than necessary to grok them
4 is what causes a useless distinction between 1 and 2 — scope leakage is scope
leakage. The explanatory mechanisms of why/whither/what etc should at best be secondary
5. is workaroundable with a [... for newvar in [rhs]]
   Possible and clunky



More information about the Python-list mailing list