可以将F#函数视为尾递归,它使用TailCall .net操作码

时间:2012-03-14 01:04:42

标签: performance f# tail-recursion tail-call-optimization

由于.net具有TailCall操作码, 如果F#函数真的是尾递归的话,这可以用来确定吗?

如果确实如此,是否有人制作了一个识别尾部和非尾部功能的VS插件?

2 个答案:

答案 0 :(得分:6)

请参阅F#团队博客上的this blog post,了解F#如何编译尾调用。

简而言之,

  1. 直接递归尾调用通常会转换为循环。
  2. 相互递归和间接非递归尾调用通常会转换为.NET尾调用。
  3. 但请查看所有血腥细节的完整帖子。

答案 1 :(得分:3)

是的,如果编译器发出tail调用指令,那么该调用将是尾递归的(从CLR 4开始,但仍有一些例外情况,它实际上不是尾递归的)。但这并不一定意味着整个函数是尾递归的。例如,我可以想象编译QuickSort函数,以便第一个递归调用不是尾递归,第二个是。

另外,仅仅因为某些函数不包含tail指令,它并不一定意味着它不是尾递归的。即使没有tail指令,JIT编译器也可以识别尾调用,并对其进行优化。

更重要的是,F#编译器有时会以非递归方式编译递归函数。这与普通尾调用优化略有不同,并且未使用tail指令,但整体效果类似。