6

que codifica 3 algoritmos factoriales:recursión de cola con Groovy

  1. En primer lugar, espero a fallar por desbordamiento de pila. No hay problema.
  2. En segundo lugar, trato de cola recusiva llamada, convertir el algoritmo anterior de recursivo a iterativo. No funciona, pero no entiendo por qué.
  3. En tercer lugar, utilizo el método trampoline() y funciona bien como esperaba.

def factorial 

factorial = { BigInteger n -> 
    if (n == 1) return 1 
    n * factorial(n - 1) 
} 
factorial(1000) // Stack Overflow 

factorial = { Integer n, BigInteger acc = 1 -> 
    if (n == 1) return acc 
    factorial(n - 1, n * acc) 
} 
factorial(1000) // Stack Overflow, why??? 

factorial = { Integer n, BigInteger acc = 1 -> 
    if (n == 1) return acc 
    factorial.trampoline(n - 1, n * acc) 
}.trampoline() 
factorial(1000) // It works 

Respuesta

2

No hay recursión de cola en Java, y por lo tanto no hay ninguno en Groovy o bien (sin el uso de algo like trampoline() como lo han demostrado)

El más cercano que he visto a este , es an AST transformation que envuelve anticipa al recursión de retorno en un bucle mientras

Editar

Tienes razón, Java (y por lo tanto maravilloso) hacen apoyar este tipo de repetición de llamada final, sin embargo, no parece trabajar con cierres ...

Sin embargo, este código (usando un método en lugar de un cierre para la llamada fact):

public class Test { 
    BigInteger fact(Integer a, BigInteger acc = 1) { 
    if(a == 1) return acc 
    fact(a - 1, a * acc) 
    } 
    static main(args) { 
    def t = new Test() 
    println "${t.fact(1000)}" 
    } 
} 

Cuando guarda como Test.groovy y ejecutada con groovy Test.groovy carreras, e imprime la respuesta:

402387260077093773543702433923003985719374864210714632543799910429938512398629020592044208486969404800479988610197196058631666872994808558901323829669944590997424504087073759918823627727188732519779505950995276120874975462497043601418278094646496291056393887437886487337119181045825783647849977012476632889835955735432513185323958463075557409114262417474349347553428646576611667797396668820291207379143853719588249808126867838374559731746136085379534524221586593201928090878297308431392844403281231558611036976801357304216168747609675871348312025478589320767169132448426236131412508780208000261683151027341827977704784635868170164365024153691398281264810213092761244896359928705114964975419909342221566832572080821333186116811553615836546984046708975602900950537616475847728421889679646244945160765353408198901385442487984959953319101723355556602139450399736280750137837615307127761926849034352625200015888535147331611702103968175921510907788019393178114194545257223865541461062892187960223838971476088506276862967146674697562911234082439208160153780889893964518263243671616762179168909779911903754031274622289988005195444414282012187361745992642956581746628302955570299024324153181617210465832036786906117260158783520751516284225540265170483304226143974286933061690897968482590125458327168226458066526769958652682272807075781391858178889652208164348344825993266043367660176999612831860788386150279465955131156552036093988180612138558600301435694527224206344631797460594682573103790084024432438465657245014402821885252470935190620929023136493273497565513958720559654228749774011413346962715422845862377387538230483865688976461927383814900140767310446640259899490222221765904339901886018566526485061799702356193897017860040811889729918311021171229845901641921068884387121855646124960798722908519296819372388642614839657382291123125024186649353143970137428531926649875337218940694281434118520158014123344828015051399694290153483077644569099073152433278288269864602789864321139083506217095002597389863554277196742822248757586765752344220207573630569498825087968928162753848863396909959826280956121450994871701244516461260379029309120889086942028510640182154399457156805941872748998094254742173582401063677404595741785160829230135358081840096996372524230560855903700624271243416909004153690105933983835777939410970027753472000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 

como una suposición, diría que la JVM no sabe cómo optimizar los cierres (como lo hace con los métodos), por lo que esta cola no se optimiza en el bytecode antes de ejecutarse

+0

[JVM tiene limitaciones en la recursión de cola] (http://stackoverflow.com/q/105834/462015) pero hay [recursión de cola en Java] (http: //books.google.ca/books?id=iPHtCfZQyqQC&lpg=PP1&dq=java%20performance%20tuning&pg=PT230#v=onepage&q&f=false) si implementó, como yo, en la segunda opción –

+0

@Arturo Tiene razón, por supuesto. .. He actualizado mi respuesta con algunos hallazgos adicionales ... –

+0

Tengo el mismo problema, pero ahora con métodos en lugar de cierres. ¡Prueba tu ejemplo con el enfoque recursivo y funciona! –

Cuestiones relacionadas