7

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

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

4

3 回答 3

3

不可能在 JavaScript 中编写 call/cc 实现:

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

快乐编码。

于 2011-11-26T23:58:52.310 回答
1

是的,有可能。看到这个问题。这是你将如何实现它:

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/

于 2012-12-24T09:29:24.667 回答
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)
})
于 2019-07-29T11:56:48.580 回答