CoffeeScript:如何在递归中使用yield

3

我正在尝试理解yield如何与递归一起使用。例如,我们有以下用CoffeeScript编写的函数,计算正整数的阶乘并返回当前累积产品:

```coffeescript factorial = (n) -> return 1 if n == 0 yield n n * factorial(n - 1) ```
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个回答

7

从CoffeeScript 1.9.1开始,"yield*"有了"yield from"的替代方案:

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 }

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)`

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接