2011-12-22 10 views
5

me encontré con la StackOverflowError para el siguiente código:java.lang.StackOverflowError en la recursión de cola clojure

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

aunque el uso del bucle sería hacer que funcione:

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

Qué va mal con el código antes sin lazo?

Respuesta

7

Su error está aquí:

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

Estás llamando recursive-reverse con un argumento (un vector). Esto llama a la misma lista de argumentos de la función, por lo que lo hace recursivamente y crea un marco de pila cada vez.

Cambiar a:

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

y que debe estar bien.

(También, tema aparte, pero yo por lo general no la comprobación de nil en lugar de '() y usando en lugar de nextrest. No creo que tenga ninguna ventaja real en términos de rendimiento o cualquier cosa, pero parece más limpio para yo.)

+1

Gracias. Claro como el cristal ahora – lkahtz

+3

'(nil? X)' podría ser mucho más rápido que '(= x())', porque el compilador puede emitir solo una operación de bytecode, la primitiva comprobación nula que usa Java. Por supuesto, este último es bastante rápido, pero sospecho que es varias veces más lento que el anterior. Da la casualidad de que esta nil-check optimizada no se ha implementado (¿todavía?), Pero es una optimización razonable que se puede hacer eventualmente. – amalloy

1

Esto funcionó para mí:

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

Se pasaron los argumentos a recursive-reverse dentro de un par de soportes innecesarios, eso es todo.

Cuestiones relacionadas