javascript - 关于 "Tail Call Optimization"文章的问题

标签 javascript optimization tail-recursion article

我有一个关于 this 的问题文章。

这段代码之间

function odds(n, p) {
  if(n == 0) {
    return 1
  } else {
    return (n / p) * odds(n - 1, p - 1)
  }
}

和这段代码

(function(){
  var odds1 = function(n, p, acc) {
    if(n == 0) {
      return acc
    } else {
      return odds1(n - 1, p - 1, (n / p) * acc)
    }
  }

  odds = function(n, p) {
    return odds1(n, p, 1)
  }  
})()

1) 我对这有多大帮助感到困惑。第二个片段是否只是有一个尾部调用,因为它在再次调用自己之前计算了它需要的东西,所以产生了更少的开销,还是我遗漏了更多东西?

据我了解,尾调用仍然没有被消除,只是被优化了。

2) 为什么还需要 oddsodds1?我也不清楚。

最佳答案

I'm confused about how much this helps. Does the second snippet simply have a tail call that creates less overhead because it calculates what it needs before it calls itself again, or is there something more I'm missing?

As I understand it, the tail call still isn't eliminated, just optimized.

如果程序的结尾是这样的:

push args
call foo
return

然后编译器可以将其优化为

jump startOfFoo

完全消除过程调用。

And why does there need to be odds and odds1 anyway? It still isn't clear to me either.

odds 的“契约(Contract)”仅指定两个参数 - 第三个参数只是一个实现细节。因此,您将其隐藏在一个内部方法中,并提供一个“包装器”作为外部 API。

我认为,您可以将 odds1 称为 oddsImpl 之类的名称,这样会更清晰。

关于javascript - 关于 "Tail Call Optimization"文章的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4707888/

相关文章:

javascript - 如何检查变量是否为 null 或空字符串或 JavaScript 中的所有空格?

php - 从 PHP 网页下载图像到文件夹

c - 事件驱动 IO 和阻塞与非阻塞

f# - 尾递归映射 f#

javascript - 如何添加指向谷歌饼图切片的链接

javascript - 在 Node.js 中提供 .html 文件时,如何在单独的目录中获取源文件以在 .html 文件中使用?

javascript - 为什么没有javascript引擎支持尾调用优化?

scala - 为什么 getOrElse 中的 return 使尾递归不可能?

C++ 优化 If 语句

c++ - 是否有一个真正有效的示例显示了 x86_64 上 ILP(指令级并行)的好处?