For example, what does the following Python code print?
funcs = list()
for i in range(10):
funcs.append(lambda: print(i))
for f in funcs:
f()For example, what does the following Python code print?
funcs = list()
for i in range(10):
funcs.append(lambda: print(i))
for f in funcs:
f()Specifically, I think, any language with closures where the loop variable exists in a scope enclosing all loop iterations with a value that is updated each iteration rather than a fresh variable in a scope local to each loop iteration has this problem.
In Ruby this wouldn't affect idiomatic looping methods like #each, but would seem likely to affect the less-idiomatic for loop, which is built on #each but has the control variable in the surrounding scope. (Not 100% certain how it desugars though.)
I don't know how it desugars, but it is indeed affected when using `for...in`
funcs = list()
for i in range(10):
funcs.append(lambda: print(i))
del i
for f in funcs:
f()
actually NameErrors during f() so I don't think it is actually closing over the i as much as the i was left in scope and the code was seemingly lazy evaluated funcs.append(lambda i=i: print(i))Maybe this example where it returns the closures from a function is convincing?
def fs():
funcs = list()
for i in range(10):
funcs.append(lambda: print(i))
return funcs
for f in fs():
f()Java forces you to final copy the variable.
let funcs = [];
;(() => {
let i;
for (i = 0; i < 10; i++) {
funcs.push(function() { console.log('i=',i); })
}
})()
for (let f of funcs) {
f.call(null);
}
(I used an IIFE to hide the "let i" from the .call to ensure it wasn't late binding to the name like the python example did)