有没有办法明确地写一个elixir函数进行尾调用优化?

时间:2015-11-28 14:11:38

标签: recursion optimization clojure elixir tail-recursion

例如,在Clojure中,您可以使用recur特殊形式来明确使用非堆栈消耗递归调用的意图,并由编译器进行验证。正如它在Clojure docs中所写的那样:

  

“在尾部位置以外重复是错误的”,   “recur功能正常,它在尾部位置的使用由编译器验证”

在elixir中,您可以将函数定义为一系列子句,并在它们之间进行递归调用。有没有办法确定定义的函数将被尾部调用优化?

1 个答案:

答案 0 :(得分:4)

编译器没有优化功能。它优化了该功能的调用。它可能是对其中相同功能的调用,它可能是对不同功能的调用,它并不重要。

...这不是Clojure的情况,其中recur只能将执行返回到最新"递归点" (无论是loop还是fn)如果没有来自外部"的帮助,例如trampoline,就无法进行相互递归。它更像是一个 bandaid 而不是一个解决方案,但问题太大了,一个合适的解决方案需要太多。

是的,有一种方法可以确保它在Elixir中得到优化:它必须是实际的tail call 。这就是全部。

  

在计算机科学中,尾调用是作为过程的最终动作执行的子程序调用。

这可以通过目视检查代码轻松确定。

如果Clojure以这种方式工作,以下两个定义将是等效的:

(defn x [] (x))     ; <- StackOverflowError if called
(defn x [] (recur)) ; <- hangs if called

但如果你想强制执行,否则就失败了,你必须这样做:

  • 编译前,e。 G。使用静态代码分析,使用一些标记来表示&#34;所需的TCO&#34;
  • 部署前,e。 G。使用会触发堆栈溢出的测试

后者似乎更实用,最简单的纯函数。

我还没有找到任何现有的解决方案。