【问题标题】:The Definitive Tail-Call Recursion Question最终的尾调用递归问题
【发布时间】:2010-02-19 00:31:41
【问题描述】:

this fiascoquestion参与辩论后,我想向整个社区提出这个问题。

尾调用优化将在哪些场景下应用于基于 .Net 的代码?

请以可靠、最新的来源或可重复的实验来支持您的答案。

【问题讨论】:

  • 您到底在寻找什么?真相还是最流行的答案?此处仅提供后者。
  • 他对证据的要求(“可靠的、最新的来源或可重复的实验”)似乎暗示他正在寻找“真相”。无论您对 SO 有何看法,他的问题都是有效的,因为 .Net 编译器和 CLR 实际上是确定性的。是否有人能够揭露这个真相仍然悬而未决。
  • 对我来说似乎非常本地化。不同版本的编译器可能会看到不同的 The Truth。当然不同的编译器会。我对标题有异议:对于一个编译器来说,本地的任何东西都不能成为任何东西的“最终问题”。
  • @dmckee,它被标记为“.net”并且标题总是与标签一起存在。必须这样,否则标题会是一堆关键词,标签会是多余的,边缘无用。
  • @dmckee well when it can be applied 独立于编译器,因为当它实际应用得很好时,它肯定取决于编译器,并且在 .NET 世界中有很多这样的编译器,有些做尾巴调用优化,有些则没有。

标签: .net tail-call-optimization


【解决方案1】:

根据 Don Syme 等人撰写的“Expert F#”,F# 做了尾调用优化。我似乎记得在 Eric Lippert 的博客上读到 C# 编译器(任何版本)都没有。如果我错了,请纠正我,埃里克。在所有情况下,尾调用优化都可以在最后一条指令调用方法时进行。这通常是对方法本身的递归调用,但并非必须如此。可以进行优化,因为可以保证不再需要当前的堆栈帧。但是,如果之后必须执行一个简单的操作,则无法执行优化。

int Fib(int n)
{
  if(n < 2)
     return 1;

  return Fib(n-1) + Fib(n-2);
}

这不能进行尾调用优化,因为在最后一次调用 Fib 返回之前无法评估 +。 (实际上我认为这也是 Expert F# 中使用的示例,但不确定。)

int Fib(int n, int a, int b)
{
  if(n == 0)
    return a+b;
  return Fib(n-1,a+b,a);
}

此版本可以进行尾调用优化,因为所有参数在最后一次调用 Fib 之前进行评估,并且在调用之后不存在要执行的操作,因此可以丢弃当前堆栈帧。

【讨论】:

    猜你喜欢
    • 2016-03-21
    • 2011-12-10
    • 1970-01-01
    • 2011-05-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-30
    • 2012-09-03
    相关资源
    最近更新 更多