Dado el siguiente código:lista inversa Scala
import scala.util.Random
object Reverser {
// Fails for big list
def reverseList[A](list : List[A]) : List[A] = {
list match {
case Nil => list
case (x :: xs) => reverseList(xs) ::: List(x)
}
}
// Works
def reverseList2[A](list : List[A]) : List[A] = {
def rlRec[A](result : List[A], list : List[A]) : List[A] = {
list match {
case Nil => result
case (x :: xs) => { rlRec(x :: result, xs) }
}
}
rlRec(Nil, list)
}
def main(args : Array[String]) : Unit = {
val random = new Random
val testList = (for (_ <- 1 to 2000000) yield (random.nextInt)).toList
// val testListRev = reverseList(testList) <--- Fails
val testListRev = reverseList2(testList)
println(testList.head)
println(testListRev.last)
}
}
¿Por qué la primera versión de la función falla (por grandes entradas), mientras que la segunda variante funciona. Sospecho que es algo relacionado con la recursividad de la cola, pero no estoy muy seguro. ¿Puede alguien darme una explicación "para tontos"?
Por qué no usar 'val = testListRev testList.reverse'? – Lutz
Esta pregunta fue hecha hace mucho tiempo, pero aquí está la respuesta a su pregunta de recursividad final. Sí, es debido a la optimización de la recursividad de la cola. En su primera implementación, case (x :: xs) => reverseList (xs) ::: List (x), después de llamar a reverseList recursivamente, el programa tiene que agregar List (x) a él. Esto significa que no se puede optimizar en un bucle, en su segundo ejemplo: case (x :: xs) => {rlRec (x :: result, xs)} rlRec es la última llamada, no hay nada que hacer después de que finalice , y es por eso que no tiene que crear un nuevo marco de pila para él. – loteq