lexical for-in/for-of loose end

Andreas Rossberg rossberg at google.com
Tue Feb 7 05:32:14 PST 2012

On 6 February 2012 21:03, Herby Vojčík <herby at mailbox.sk> wrote:
> Well, in fact what I proposed was not changing the behaviour of
> head-closures, but body-closures. Basically, the idea was: let the loop run
> in legacy semantics (only one block for the whole for-loop). All closures
> (head ones and body ones) access the same let-var and modify it.
> But, for at the end of each iteration, if body-closures were created, rebind
> that closures to copy (or, better, child) of actual execution record with
> let-var being local (de-facto simulating per-iteration binding, but lazily;
> and only for async closures).

What are the "closures that were created", and how do you keep track
of them? 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]())

And imagine the fun you can have with generators!

> Spec-wise, I think it only needs to define two things, CopyExecutionRecord,
> which Grant already mentioned, or something similar like
> CopyWithFixedVars(ExecutionRecord, vars-to-fix) and
> ReplaceExecutionRecordBinding to allow closure(s) bound to original
> execution record re-bind it to its copy created by the former.

Allow me to be blunt: this is literally raping the concepts of
declarative environment and lexical closure. It is a hack, completely
non-orthogonal, and I predict that the hidden statefulness it
introduces to closure environments would be going to bite back in gore

Seriously, before we consider going there, I'd rather have a step on
the break and stick to C-style for-semantics.


More information about the es-discuss mailing list