On 7 February 2012 15:40, Grant Husbands <[email protected]> wrote: > On 7 February 2012 13:32, Andreas Rossberg <[email protected]> wrote: >> What should the following do? >> let a = [], b = [], c = [], d = [] >> for (int i = 0, f = function(){ return function() { ++i } }; i < 10; >> d[i] = function() { return i }, ++i) { >> a[i] = f; >> b[i] = f(); >> c[i] = function(){ return i } >> } >> print(c[2]()); print(d[2]()) >> a[4]()(); print(c[4]()); print(d[4]()) >> b[7](); print(c[7]()); print(d[7]()) > > Here's what it does under the proposed scheme: > c[2]() -> 2 > d[2]() -> 3 > a[4]()() increments the i that is 10 to 11. > c[4]() -> 4 > d[4]() -> 5 > b[7]() increments the i that is now 11 to 12. > c[7]() -> 7 > d[7]() -> 8 > Basically, the closures lexically within the loop init always see the > latest version of i. Those lexically within the rest of the loop > always see the i that was available at the end of their iteration. The > iteration part of the loop is considered to be at the start. A related > gotcha is that d[9]() would return 12, if added to the end of that > sequence of calls. (I'm answering to the best of my ability, not > trying to defend anything.)
But note that the environment in b's closures is not the for-loop environment. Instead, it is a local environment, whose parent is the for-loop environment. To make that case work, it is not enough to be able to modify the [[Scope]] environment of closures -- in general, you'd need to swap out arbitrary parts of an environment chain. >> Allow me to be blunt: this is literally raping the concepts of >> declarative environment and lexical closure. It is a hack, completely >> non-orthogonal, > > I think that may be more than blunt; it is strongly emotive and also > vague enough that it can't really be answered. However, I and others > do share the concern that it may introduce too much complexity, and > then only really add support for a very rare usage. You are right, I should have been more careful. I am sorry about that. This is not merely a question of complexity, though. It's more fundamental. Environments are immutable mappings from names to locations -- that's a basic axiom of lexical scoping. Breaking it will have unforeseeable consequences. That may be vague, I agree, but I prefer not to find out concretely. :) Subtle combinations of higher-orderness and state rarely let you down in terms of nasty surprises. >> Seriously, before we consider going there, I'd rather have a step on >> the break and stick to C-style for-semantics. > > I think we wouldn't need to go that far; your generalization of Mark's > desugaring covers plenty of use cases and certainly the one of most > common loop/closure gotchas. To my understanding, that's the favoured > idea, so far, and we're just exploring this one to see where it might > lead. I am fine with either. So far I have favoured fresh-variables-per-iteration, but the current discussion has raised some doubts in the back of my mind. /Andreas _______________________________________________ es-discuss mailing list [email protected] https://mail.mozilla.org/listinfo/es-discuss

