在JavaScript中模拟/使用Continuations?

时间:2011-12-11 06:30:54

标签: javascript continuations

我有一个计算数组中数字乘积的函数。该功能应该像这样工作

function prod (array){
//compute and return product
}

var arr = [1,2,3,0,4,5,0,6,7,8,0,9];

the function call:
prod(arr); //should return 6
prod(arr); //should return 20
prod(arr); //should return 336 (6*7*8)
prod(arr); //should return 9
prod(arr); //should return 0
prod(arr); //should return 0
prod(arr); //should return 0

在方案中,通过存储函数的先前状态(在函数退出点之前捕获函数的状态)see this

,继续执行此操作。

因此,简而言之,我希望javascript函数在不同的时间返回不同的值,每次都传递相同的参数。

JavaScript是一种设计良好的语言,所以我希望必须有能够模仿这一点的东西。如果JS中没有任何东西可以做到这一点,我不介意以失败告终并继续前进。所以,随意说它不可能。

感谢。

4 个答案:

答案 0 :(得分:3)

JavaScript无法支持延续:它缺少尾调用。

通常我会写这个以使用各种“队列”,虽然CPS也可行(只有一个有限的堆栈:-)请注意,其他状态也可以在闭包中捕获,使其成为“显式”继续“各种......在非常粗略的意义上。”

使用闭包和队列的示例:

function prodFactory (array){
   // dupe array first if needed, is mutated below.
   // function parameters are always locally scoped.
   array.unshift(undefined)  // so array.shift can be at start
   // also, perhaps more closured state
   var otherState
   // just return the real function, yippee!
   return function prod () {
      array.shift()
      // do stuff ... e.g. loop array.shift() and multiply
      // set otherState ... eat an apple or a cookie
      return stuff
   }
}

var prod = prodFactory([1,2,3,0,4,5,0,6,7,8,0,9])

        // array at "do stuff", at least until "do stuff" does more stuff
prod()  // [1,2,3,0,4,5,0,6,7,8,0,9]
prod()  // [2,3,0,4,5,0,6,7,8,0,9]
prod()  // [3,0,4,5,0,6,7,8,0,9]

快乐的编码。


“完成实施”。虽然这个特殊问题可以避免数组变异并且只使用索引:同样的概念也适用。 (嗯,略有不同。只有一个索引,关闭的变量将被改变,而使用这种方法,一个对象被改变。)

function prodFactory (array) {
   array = array.slice(0)
   return function prod () {
      var p = 1
      for (var n = array.shift(); n; n = array.shift()) {
        p *= n
      }
      return p
   }
}

var prod = prodFactory([1,2,3,0,4,5,0,6,7,8,0,9])

prod()  // 6
prod()  // 20
prod()  // 336

答案 1 :(得分:2)

您可以为函数提供一个将在调用之间记住的属性:

function prod (array){
   if (typeof prod.index === "undefined" || prod.currentArray != array) {
      prod.currentArray = array;
      prod.index = 0;
   }

   if (prod.index >= array.length)
      return 0;

   //compute and return product
   var p = 1,
       c;
   while (prod.index < array.length) {
      c = array[prod.index++];
      if (c === 0)
         return p;
      p *= c;
   }
   return p;
}

我只是从你对应该返回的内容的描述中猜测,在单独调用函数时,它应该取所有数字的乘积,但不包括下一个零或数组的结尾。数组结束后调用应该返回0?我可能有这个算法的错误,但你知道我建议记住调用之间的函数状态。

我添加了一个属性来记住当前正在处理的数组。只要你继续将相同的数组传递给函数,它将继续使用下一个元素,但如果你传递一个不同的数组,它将重置......

答案 2 :(得分:1)

你可以试试像

这样的东西
var index = 0;
function prod (array){
    if(index < array.length){
    var prod=1;
    for(int i=index;i<array.length;i++){
        if(array[i] != 0){
            prod = prod * array[i];
        }
        else{
            index = i+1;
            return prod;
        }
    }
}
return 0;   
}

这将在每次调用函数时更新全局变量索引。

答案 3 :(得分:1)

您在这里寻找的是generators。截至1.7,JavaScript supports them