unintuitive for-loop behavior

Random832 random832 at fastmail.com
Fri Sep 30 23:25:05 EDT 2016


On Fri, Sep 30, 2016, at 20:46, Gregory Ewing wrote:
> 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 don't think that's true. I think this is logic that is excessively
tied to the toy examples that are used to illustrate the problem.

You don't think it's common [at least, as far as defining a lambda
inside a loop at all is common] to do something like this?

for a in collection:
    b = some_calculation_of(a)
    do_something_with(lambda: ... b ...)

There's a reason that C++'s solution to this problem is an explicit list
of what names are captured as references vs values inside the lambda.

I think what we really need is an explicit expression/block that gives a
list of names and says that all uses of that name in any function
defined inside the expression/block refer to the value that that
expression had when the expression/block was entered.

Suppose:

[final exponent: lambda base: (base ** exponent) for exponent in
range(9)]

for exponent in range: 9
   final exponent:
       def pwr(base):
           return base ** exponent
       result.append(pwr)

for a in collection:
    b = some_calculation_of(a)
    final b: do_something_with(lambda: ... b ...)

Maybe do stuff like "for final var in ..." for both loops and
comprehensions, or "final var = expr:", depending on if we can make the
intuitive-looking syntax well-defined. "final" is a placeholder for
whatever new keyword is chosen, though I will note that even though IIRC
Guido doesn't like this sort of thing, it would only appear next to
identifiers in the proposed syntax and two identifiers not joined by an
operator is meaningless.

An alternative would be, considering that the problem only applies to
nested functions, to expand the "keyword argument" hack into a
less-"hacky" and less verbose solution, e.g. "lambda base, $exponent:
base ** exponent" - creating, in effect, a keyword argument with the
name 'exponent' that can't actually be passed in to the function.



More information about the Python-list mailing list