4 ms·
In fact most languages suffer from this, but it's more acute in go because of how easy it is to create closures and threads. For example, what does the followi
by assbuttbuttass 3y ago
In fact most languages suffer from this, but it's more acute in go because of how easy it is to create closures and threads.
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()
- sharno 3y agoInteresting, didn't think about closures in Python before. It seems that JS has the same behavior. Java forces you to final copy the variable.
- agumonkey 3y agoI lost track of ES scoping rules but apparently `for (var i ...) { ... }` doesn't capture (legacy behavior) while `for (let i ...) { ... }` will.
- mdaniel 3y agoI don't think that's limited to just `var`, as a `let` outside of the `for` will do the same 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)
- dragonwriter 3y ago> most languages suffer from this 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.)
- masklinn 3y ago> 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`
- mdaniel 3y agoI didn't know the answer to this, but it seems like this actually behaves closer to `funcs.append("""print(i)""")` since 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
- InfamousRece 3y agoRight. In this example lambda does not capture i at all. You would need something like funcs.append(lambda i=i: print(i))
- assbuttbuttass 3y agoNo, it definitely captures 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()
- germandiago 3y agoprints all 9s.
- assbuttbuttass 3y agoPython has real closures. In my example, it is closing over i. In your example, you're deleting the closed-over variable. It's a bit weird, and Python is the only language that I know of that lets you do this.
- deleted 3y ago[deleted]
- cutler 3y agoIt's called late binding and some Pythonistas actually consider it a feature.