CoffeeScript:使用yield和递归

时间:2015-02-26 05:03:23

标签: javascript recursion coffeescript yield

我试图了解yield如何处理递归。例如,我们在CoffeeScript中有以下函数来计算正整数的阶乘并返回当前的累积乘积:

prod = 1
f = (n) ->
  if n > 0
    prod = n * prod
    yield prod
    f(n-1)

因此,如果我们使用a = f(3)调用此函数并逐步执行a.next(),我希望看到类似

的内容
{value: 3, done: false} // prod = 3 * 1
{value: 6, done: false} // prod = 3 * 2
{value: 6, done: true}  // prod = 3 * 2 * 1

但是,实际输出是

{value: 3, done: false}
{value: {}, done: false}
{value: undefined, done: true}
{value: undefined, done: true}
...

有人能解释一下这里发生了什么吗?我应该如何更改代码以获得所需的结果?谢谢!

2 个答案:

答案 0 :(得分:6)

@phenomnomnominal,从CoffeeScript 1.9.1开始,有"来自" for" yield *":

prod = 1
f = (n) ->
  if n > 0
    prod = n * prod
    yield prod
    yield from f(n-1)

gen = f(3)

loop
    ngen = gen.next()
    console.log ngen
    break if ngen.done

这应该产生:

{ value: 3, done: false }
{ value: 6, done: false }
{ value: 6, done: false }
{ value: undefined, done: true }

答案 1 :(得分:2)

我在JS中运行以下代码,在FireFox中运行:

var prod = 1;
var f = function*(n) {
  if (n > 0) {
    prod = n * prod;
    yield prod;
    yield* f(n - 1);
  }
};

a = f(3);
console.log(a.next()); // Object { value: 3, done: false } 
console.log(a.next()); // Object { value: 6, done: false } 
console.log(a.next()); // Object { value: 6, done: false }
console.log(a.next()); // Object { value: undefined, done: true }

但是,看起来CoffeeScript还不支持yield*。可能是某人为项目做出贡献的好机会!为了解决这个问题,你可以使用反引号来传递JS:

prod = 1
f = (n) ->
  if n > 0
    prod = n * prod
    yield prod
    `yield* f(n-1)`