2011-12-22 77 views
5

我遇到的StackOverflowError以下代码:java.lang.StackOverflowError的Clojure中尾递归

(defn recursive-reverse 
    ([coll] (recursive-reverse [coll nil])) 
    ([coll acc] 
    (if (= coll '()) acc 
     (recur (rest coll) (cons (first coll) acc))))) 

虽然使用循环会使其工作:

(defn recursive-reverse [lst] 
    (loop [coll lst acc nil] 
    (if (= coll '()) acc 
     (recur (rest coll) (cons (first coll) acc))))) 

错在现有代码没有循环?

回答

7

你的错误是在这里:

([coll] (recursive-reverse [coll nil])) 

你打电话recursive-reverse有一个参数(矢量)。这将调用该函数的相同参数列表,因此它会递归执行并每次创建一个堆栈帧。

将其更改为:

([coll] (recursive-reverse coll nil)) 

,你应该是正确的。

(同样,单独的问题,但我一般不检查nil,而不是'()和使用next而非rest,我不认为它在性能或任何方面的任何真正的优势,但它似乎吸尘器我)。

+1

谢谢。现在清澈透明。 – lkahtz 2011-12-22 01:08:40

+3

'(nil?x)'可能比'(= x())'快得多,因为编译器只能发出一个字节码操作,即Java使用的原始空值检查。当然,后者非常快,但我怀疑它比前者慢好几倍。碰巧,这个优化的无检查没有实现(但?),但这是一个合理的优化,最终可能会做出。 – amalloy 2011-12-22 02:05:57

1

这为我工作:

(defn recursive-reverse 
    ([coll] (recursive-reverse coll nil)) 
    ([coll acc] 
    (if (= coll '()) acc 
     (recur (rest coll) (cons (first coll) acc))))) 

您传递的参数recursive-reverse几个不必要的括号内,仅此而已。