san*_*ari 5 optimization recursion tail-recursion clojure elixir
例如,在 Clojure 中,您可以使用recur 特殊形式来明确使用非堆栈消耗递归调用的意图,并由编译器验证。正如它在 Clojure文档中所写:
“在尾部位置以外的重复是一个错误”,“recur 是功能性的,它在尾部位置的使用由编译器验证”
在 elixir 中,您可以将函数定义为一系列子句,并在它们之间进行递归调用。有没有办法确定定义的函数将进行尾调用优化?
编译器不会优化函数。它优化了对该函数的调用。可能是调用了里面的同一个函数,也可能是调用了不同的函数,没关系。
...Clojure 的情况并非如此,在那里recur只能将执行返回到最新的“递归点”(无论是loop还是fn),这使得在没有“外部帮助”的情况下不可能进行相互递归,例如trampoline。它更像是一个创可贴而不是解决方案,但问题太大了,一个合适的解决方案需要太多。
是的,有一种方法可以确保它在 Elixir 中得到优化:它需要是一个实际的尾调用。就这样。
在计算机科学中,尾调用是作为过程的最终动作执行的子程序调用。
这可以通过目视检查代码轻松确定。
如果 Clojure 以这种方式工作,则以下两个定义将是等效的:
(defn x [] (x)) ; <- StackOverflowError if called
(defn x [] (recur)) ; <- hangs if called
Run Code Online (Sandbox Code Playgroud)
但是,如果您想强制执行此操作并否则失败,则必须执行以下任一操作:
后者似乎更实用,最简单的纯函数。
我还没有找到任何现有的解决方案。