Clojure JVM 7/8的改进

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/