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