On Wed, Nov 18, 2020 at 9:54 PM Greg Ewing firstname.lastname@example.org wrote:
Essentially the idea is this: If the loop body contains a def or lambda that captures the loop variable, then on each iteration, a new binding is created, instead of changing an existing binding.
Note that this is *not* the same as introducing a new scope. All the bindings share the same name, and from the perspective of code outside the nested function, nothing changes -- the name is still bound to the most recent value, and can still be accessed after the loop has finished.
The problem I see is that nested functions referring to the same variable can be defined outside loops as well. If you define a helper before the loop that refers to the loop variable, it won't work inside the loop or ever again after the loop has terminated. Even if the helper has nothing to do with the loop and just uses the same generic variable name like "item", it'll break. It's fairly common to reuse the same identifier for different purposes inside functions.
As much as I hate the current behavior, I feel like the proposed behavior is too confusing and weird.
Another problem is that the capturing behavior would depend on whether the variable is in a function or module or class scope, since cells only exist in function scopes.
Also, "while x := get_next_thing():" loops wouldn't behave consistently with for loops.
for new x in some_iterator:
I don't think special syntax would help. I've been bitten by this problem fairly often, and 100% of the time I've been able to solve it by adding x=x to the argument list to capture by value. I can't imagine I'd ever want to capture a loop variable by reference, especially if the cell being referenced no longer has a name outside of the nested function when the nested function is called. I get in trouble because I forget to write x=x where it's necessary, but if I forget to write x=x then I'd forget to write "new x" too.