Ral*_*lph 14 tail-recursion clojure invokedynamic
Rich Hickey和其他人已经提到Clojure不会从即将推出invokeDynamic的JVM 7或8计划中获得显着改进,但是会看到尾递归的性能提升.
尾递归是否会对其产生影响
(fn [...] (recur ...))
Run Code Online (Sandbox Code Playgroud)
要么
(loop [...] (recur ...))
Run Code Online (Sandbox Code Playgroud)
我不希望它们得到任何更快,因为编译器可能已经生成循环结构.
nic*_*kik 17
非你的例子会更快,因为如果你使用recur你已经告诉编译器你有一个尾递归函数,这允许编译器生成使用的字节代码goto(像一个普通的命令循环)
如果JVM获得尾调用优化,那么当然有一些好处.
您不必再使用recur(如果您不想),那么您可以编写这样的函数(尾递归函数)
(defn testfn [n] (when (not= 1000 n) (testfn n)))
Run Code Online (Sandbox Code Playgroud)
现在,JVM无法检测到尾递归.通过添加尾部调用优化,JVM能够看到上面的函数,就像你已经编写了这个(因此得到了必要的循环速度):
(defn testfn [n] (when (not= 1000 n) (recur n)))
Run Code Online (Sandbox Code Playgroud)
所以这不是一个很大的改进,但还有另一种情况,尾部调用优化真的很棒.
如果你有相互调用的函数(有时甚至超过两个)并且不需要保持堆栈(尾递归),JVM可以优化它们.现在这是不可能的,因为你无法告诉recur跳转到其他功能.这是一个例子.
(defn even [n] (if (zero? n) true (odd? (dec n)))
(defn odd [n] (if (zero? n) false (even (dec n)))
Run Code Online (Sandbox Code Playgroud)
如果您尝试使用大量数据,那么您将会打击堆栈,但是使用尾调优化则不会.
我还剩下一点点.有一个函数调用trampoline,允许你已经这样做(编程风格和一些开销稍有变化)而不是解释trampoline我将引用你的博客,它正是这样做:
http://pramode.net/clojure/2010/05/08/clojure-trampoline/