呼叫/ CC与闭包

时间:2011-11-26 22:29:39

标签: javascript callcc

Wikipedia提到“在任何支持闭包和正确尾调用的语言中,都可以用延续传递方式编写程序并手动实现call / cc。”

如何在javascript中实现此功能?我知道javascript不做tco,但假设堆栈空间没有用完

3 个答案:

答案 0 :(得分:1)

无法在JavaScript中编写call / cc实现:

JavaScript不符合“正确的尾调用”的要求(无需额外的堆栈创建)。但是,我相信使用异常的形式延续,例如Jetty中的延续,是可能的。 “CPS”就像传递函数对象一样简单,尽管最终它会遇到堆栈问题,除非偶尔退出。

快乐的编码。

答案 1 :(得分:1)

有可能

https://github.com/zaoqi/callcc.js/blob/master/callcc.js

async function callcc(f){
return await new Promise((resolve,reject)=>{
const resolve_packed=(v)=>{
    resolve(v)
    return new Promise((resolve,reject)=>{})
}
f(resolve_packed).then(resolve).catch(reject)
})
}

使用它:

test('test1',()=>{
expect.assertions(1)
expect((()=>{
async function q(k,v){
    console.log('testing1')
    await k(v)
}
return callcc(async function(k){
    console.log('testing0')
    await q(k,133)
    console.error('test error')
})
})()).resolves.toBe(133)
})

答案 2 :(得分:0)

是的,这是可能的。见question。这就是你实现它的方式:

Function.prototype.async = async;

function async() {
    setTimeout.bind(null, this, 0).apply(null, arguments);
}

function callcc(f, cc) {
    f.async(cc);
}

然后您可以按如下方式使用它:

pythagoras.async(3, 4, alert);

function pythagoras(x, y, cont) {
    callcc.async(square.bind(null, x), function cc(x_squared) {
        callcc.async(square.bind(null, y), function cc(y_squared) {
            add.async(x_squared, y_squared, cont);
        });
    });
}

function square(x, cont) {
    multiply.async(x, x, cont);
}

function multiply(x, y, cont) {
    cont.async(x * y);
}

function add(x, y, cont) {
    cont.async(x + y);
}

你可以在这里演绎这个演示:http://jsfiddle.net/brZrd/