> What happens if you don't supply a function but another type, or none?
The simplest thing is to specify it as a runtime error if the argument to shift
is not callable. You're right that there's an overhead to constructing a new
function. But it gives you flexibility that's otherwise a pain for the
programmer. More below.
> Would 42 still be "returned" by shift? Or is it actually the returned value
> in k, that gets a send method augmented to it?
I don't understand this question-- do you mean whatever value the handler
function (in the example, function(k) { return k }) returns? Then no, there's
no augmentation or mutation here. The continuation is represented as an object
with three methods:
- send(v): pushes the suspended activation back onto the stack and uses v as
the result of the shift expression
- throw(v): pushes the suspended activation and throws v from the shift
expression
- close(): pushes the suspended activation and performs a return (running any
relevant finally blocks first)
(This is all just what JS 1.7 generators do.)
A simpler representation for captured continuations is just a function. But as
Kris pointed out in an earlier thread, this is inconvenient for the "throw" and
"close" cases.
> It'd be cleaner if it was just shift()
You might think so, since the semantics seems simpler-- but it would lead to
uglier programs. You're not affording the writer of the function doing the
shift any ability to specify what to do after the shift, and you're not giving
them the ability to communicate any data to the caller. This requires them to
coordinate with clients to save any additional action in some side-channel,
e.g.:
// library
function gen(thenWhat) {
...
thenWhat.action = function() { ... /* do more stuff */ ... };
let received = shift();
...
}
// client
var k = gen({ action: function() { } });
> But maybe I'm knifing an entire API here I don't know about :) Otherwise the
> send method seems redundant.
I'm not sure what the send method has to do with it-- it sounds like I may not
have explained clearly enough. The semantics of shift is to capture and pop the
current activation, reify it as an object with the three methods I describe
above (send, throw, close) and call the handler function with this reified
activation object as its argument. It's then up to the program to decide
when/whether to continue the captured function by calling its methods.
Note that this means that when you use the shift operator, the handler function
is executed immediately, whereas the rest of the captured function is suspended
and not continued until some later time. This is the opposite of patterns like
event callbacks and CPS, where the code in the callback is called at some later
time, but the rest of the current function is continued immediately.
Dave
_______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss