javascript - 为什么递归生成器函数在 ES2015 中不起作用?

标签 javascript recursion ecmascript-6 generator

我试图理解 ES2015 中的生成器,并用它创建了一个递归阶乘函数。但它不起作用。我已经提到了已经存在的问题,例如 this关于这个话题,但没有帮助。

function* fact (n) {
   if (n < 2) {
     yield 1;
   } else {
     yield* (n * fact(n-1));
   }
}

let b = fact(5);
console.log(b.next()); 

谁能找到我在这里遗漏的任何明显问题?我在带有 JavaScript-1.7 的 JSFiddle 中使用它 here

最佳答案

Can anyone find any obvious issues I am missing here?

fact 返回一个迭代器,但您正试图将它与一个数字 相乘:n * fact(n-1)。那行不通!

因为 fact 返回一个迭代器,但您还想将迭代器的最后一个值与 n 相乘(即它不是尾递归的),您不能简单地yield* 要么。
您需要显式迭代内部调用的结果,重新发出值并记住最后一个值,以便您可以对其进行倍增:

function* fact (n) {
   if (n < 2) {
     yield 1;
   } else {
     let last;
     for(last of fact(n-1)) {
       yield last;
     }
     yield n * last;
   }
}

Array.from(fact(5)); // [1, 2, 6, 24, 120]

如果将函数更改为尾递归,它会更短(更好),但结果也会不同(因为我们以不同的顺序执行操作,至少在这个实现中):

function* fact (n, acc=1) {
   yield acc
   if (n > 1) {
     yield* fact(n-1, acc * n);
   }
}
Array.from(fact(5)); // [1, 5, 20, 60, 120]

我个人只会写一个非递归版本:

function* fact (n) {
  let result = 1;
  let i = 0;
  while (i < n) {
    yield result = result * ++i;
  }
}
Array.from(fact(5)); // [1, 2, 6, 24, 120]

关于javascript - 为什么递归生成器函数在 ES2015 中不起作用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37178782/

相关文章:

javascript - 具有嵌套 View 的 MVC

javascript - 绘制函数导致闪烁 - Javascript

javascript - 如何包含特定于每个 View 的javascript文件angularjs

javascript - 在对象树中查找根和任意对象之间的对象

javascript - 如何使用 JavaScript 递归将一个模式循环到另一个模式中,如果没有手动给出任何参数,它应该在什么时候停止循环?

javascript - Express Router : How do I get parameters?(不是 URL 段)

php - 通过引用递归函数

javascript - 一次清除所有表单字段,reactjs

module - 使用 TypeScript 的默认导入

javascript - 打破 JavaScript ES6 函数不使用 return