2011-12-22 13 views
5

ho incontrato lo StackOverflowError per il seguente codice:java.lang.StackOverFlowError in clojure ricorsione in coda

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

pur usando ciclo sarebbe farlo funzionare:

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

ciò che va male con il codice prima senza anello?

risposta

7

tuo bug è qui:

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

si sta chiamando recursive-reverse con un argomento (un vettore). Questo chiama lo stesso elenco di argomenti della funzione, quindi lo fa in modo ricorsivo e crea uno stack frame ogni volta.

modificarla in:

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

e si dovrebbe essere giusto.

(Inoltre, questione a parte, ma mi sarebbe generalmente il controllo per nil piuttosto che '() e utilizzando next piuttosto che rest. Io non penso che abbia un reale vantaggio in termini di prestazioni o di qualsiasi cosa, ma sembra più pulito me.)

+1

Grazie. Adesso cristallino. – lkahtz

+3

'(nil? X)' potrebbe essere molto più veloce di '(= x())', perché il compilatore può emettere solo una singola operazione bytecode, il primitivo controllo nullo utilizzato da Java. Naturalmente, quest'ultimo è abbastanza veloce, ma ho il sospetto che sia più lento del precedente. Come succede, questo controllo nil ottimizzato non è implementato (ancora?), Ma è una ragionevole ottimizzazione che potrebbe essere fatta alla fine. – amalloy

1

questo ha funzionato per me:

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

avete passato gli argomenti per recursive-reverse all'interno di un paio di parentesi inutili, questo è tutto.

Problemi correlati