5 ms·
No they are not exactly the same. From the link you posted: "all uses of the name within the block are treated as references to the current block" The Python
by willtim 9y ago
No they are not exactly the same.
From the link you posted: "all uses of the name within the block are treated as references to the current block"
The Python folks call them "late binding closures" and they are frequently discussed as "gotchas".
Essentially lexically scoped variables are captured as references to mutable state. Java did not make this mistake, perhaps because they had Guy Steele (of Scheme fame) on the committee. It is a questionable default that ultimately just destroys ones ability to reason about programs.
- mbrock 9y agoWait, isn't that exactly how lexical scoping in Scheme works? That's how you implement "objects" using lambdas. You make closures that mutate their closed-over bindings.
- empthought 9y agoThe question is if you mutate the variable, create a closure, mutate the variable, create a closure, and so on -- do those closures -- when executed -- each use the value that the variable had at the time the individual closure was created, or do they all use the latest value that the variable had? Scheme (and other academic languages) do the first, Python (and other scripting languages) do the second. But the problem with program comprehensibility comes from doing these gymnastics with block scope and anonymous functions in the first place. The right thing to do is to give things proper names and interfaces. In other words, both what Scheme does and what Python does are bad for reasoning about programs, precisely because the semantics of what should be done in this scenario are implicit and unable to be discerned solely by reading the code. Since either behavior is non-obvious, and understanding the program relies on this implicit behavior, the practice of mutating a variable while repeatedly creating closures over it should be avoided.
- kazinator 9y agoNo, multiple closures in Scheme will not capture different values of the same, mutated variable. For that to happen, the block has to be re-entered such that a fresh binding is created for those variables. That is not mutation. Scheme's version of the do loop actually performs fresh binding, rather than mutation, so lambdas in the do loop capture the iterations separately. If you mutate a variable with set!, all the closures over that variable see the change.
- empthought 9y agoThanks, "mutate" was definitely the wrong word in my post. The trouble here is that Python doesn't have syntax to do a binding rather than an assignment.
- empthought 9y ago> It is a questionable default that ultimately just destroys ones ability to reason about programs. If that destroys one's ability to reason about programs, then one never really had the ability to reason about one's programs in the first place. It's not like nested block scopes are some boon to program comprehensibility anyway.