Skip to content

Instantly share code, notes, and snippets.

@jooyunghan
Created December 3, 2017 13:15
Show Gist options
  • Save jooyunghan/0dab021c293b0d14b7039077c8b8594c to your computer and use it in GitHub Desktop.
Save jooyunghan/0dab021c293b0d14b7039077c8b8594c to your computer and use it in GitHub Desktop.
One-shot continuation using symmetric coroutines
const coro = require('symcoro');
const {create, transfer} = coro;
// Figure 4. Implementing one-shot continuations with symmetric coroutines
// http://www.inf.puc-rio.br/~roberto/docs/MCC15-04.pdf
function* call1cc(f) {
// save the continuation "creator"
let currentCoro = coro.current;
// invoking the continuation transfers control
// back to its creator
function* cont(val) {
if (currentCoro === null) {
throw new Error('one shot continuation called twice');
}
yield* coro.transfer(currentCoro, val);
}
const val = yield* coro.transfer(
coro.create(function*() {
const v = yield* f(cont);
yield* cont(v);
})
);
// when control is transfered back, the continuation
// was "shot" and must be invalidated
currentCoro = null;
// the value passed to the continuation
// is the return value of call1/cc
return val;
}
coro.run(function*() {
return yield* call1cc(function*(cont) {
yield* transfer(create(function* nested() {
yield* transfer(create(function* nestedAgain() {
yield* cont(42);
}));
}));
});
}, console.log); //42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment