the other is a much more radical change to the way the language works, which I'm not altogether convinced is a good or useful thing.

It's essential to the control abstraction programmability. Take a look at the examples. .. Return from a block in JS today returns from the enclosing function. Same for return from a block-lambda in a function. It's an early error to return from global code, and will be in a block-lambda in global code.

Why is this so bad? JS programmers return, break, and continue from blocks all the time.

The examples focus on inline uses of block_lambdas,
but block_lambdas can do a lot more than that (or so I think - until we see more complete semantics, I have to extrapolate from the examples; perhaps the variations below are not intended). Again, that doesn't have to be bad, but the consequences need to be investigated and taken into consideration.

For instance, block_lambdas seem to include a form of generalized jump, a callable thing that does not return to the caller (Tennent mentioned such things as 'sequels',
so they were probably known in Algol times, but I have
not seen them implemented, short of (delimited) continuations).
We just need to ensure that the callable's definition context is still active:

function A() {
   let ret = {|x| return x; }; // sequel
   let inc = {|x| x+1 };    // function
   let j = 0;
   while(true) {
       if (j > 3)
           ret(j); // leave loop, and A
       else
           j = inc(j); // continue loop
   }
}

Calling a sequel like 'ret' is always a tail call, because it never returns to the caller, it returns elsewhere. In
that sense, it is a generalized jump.

The break/continue variant of sequels also makes it possible to replace labeled breaks and continues with sequels:

A: while(true) {
   let continue_A = {|| continue; };
   B: while (true) {
let break_B = {|| break; }; C: while(true) {
           if (cond)
               continue_A();
           else
               break_B();
       }
   }
}

The best approximation I have of what return/break/continue
mean in a block_lambda is based on lexical scoping, to the nearest enclosing function or loop (but nullable: when the definition context is no longer active, return/break/continue throw a runtime error).
That means that functions and loops have implicit bindings
(for return and for break/continue), and the 'break_B' example above is really analogous to the 'let self = this;' pattern: a way ot keeping the next outer implicit binding accessible. Of course, block_lambdas do not introduce this problem, they introduce a new workaround. Still, it is interesting to look at the new
programming patterns that become possible.

Again, this is just guessing based on reading the examples in the strawman - it could be completely off the mark. Informal but complete semantics would help to understand what is supposed to be possible and what not. Further decisions cannot be based on syntax or selected examples alone.

Claus


_______________________________________________
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss

Reply via email to