The real issue is that Python's for construct doesn't create a new lexical scope for the body.
In either Perl 5 or Perl 6, both of which use mutable variables, the corresponding code does the right thing (although Perl 5 only does so if you actually use a newly defined lexical: as in "for my $m ('do', 're', 'mi') {...}").
Unfortunately, Python's implicit declaration of lexicals means that it would be difficult to do a for loop with an iteration variable that isn't lexical to the loop body if that was the default (where would you put the "nonlocal" statement?).
> The real issue is that Python's for construct doesn't create a new lexical scope for the body.
Yes and no, that's what leads the author to notice the "issue", but it does not actually solve the problem (if closing over a mutable environment is to be seen as a problem), it just pushes it back.
It can be argued that loops is the most common case where this is a problem (by quite a long shot) and working around that issue (by creating statement-level scopes or by using internal iterators [0]) would lead to the vast majority of users extremely encountering it. But still...
[0] internal iterators being the reason why Smalltalkers never encounter that issue, and rubyists and modern JS-developers (using Array.prototype.forEach or equivalent library-specific features) rarely do.
This is why CoffeeScript introduced the "do" keyword. I'd have to agree that, while in Javascript in particular this is considered a rookie mistake, loop variables not being closed over is a rather confusing phenomenon for newcomers.
CoffeScript is a very good language, but in my opinion, it should not be an excuse to not learn and understand such confusing behaviors of javascript. It will eventually bite any such newcomers. Not that you meant this, just saying.
This problem was solved brilliantly by Clojure. Everything is immutable by default, and modifications of references happen at explicit points in the flow, with well-defined semantics.
[+] [-] ekiru|15 years ago|reply
In either Perl 5 or Perl 6, both of which use mutable variables, the corresponding code does the right thing (although Perl 5 only does so if you actually use a newly defined lexical: as in "for my $m ('do', 're', 'mi') {...}").
Unfortunately, Python's implicit declaration of lexicals means that it would be difficult to do a for loop with an iteration variable that isn't lexical to the loop body if that was the default (where would you put the "nonlocal" statement?).
[+] [-] masklinn|15 years ago|reply
Yes and no, that's what leads the author to notice the "issue", but it does not actually solve the problem (if closing over a mutable environment is to be seen as a problem), it just pushes it back.
It can be argued that loops is the most common case where this is a problem (by quite a long shot) and working around that issue (by creating statement-level scopes or by using internal iterators [0]) would lead to the vast majority of users extremely encountering it. But still...
[0] internal iterators being the reason why Smalltalkers never encounter that issue, and rubyists and modern JS-developers (using Array.prototype.forEach or equivalent library-specific features) rarely do.
[+] [-] stdbrouw|15 years ago|reply
[+] [-] sharat87|15 years ago|reply
[+] [-] glenjamin|15 years ago|reply
For my part, I always found having block scope inside conditionals to feel weird.
[+] [-] adambyrtek|15 years ago|reply
[+] [-] dons|15 years ago|reply
[+] [-] Locke1689|15 years ago|reply