Un corte directo y pegar el siguiente algoritmo:especie de "programación Scala" causa desbordamiento de pila
def msort[T](less: (T, T) => Boolean)
(xs: List[T]): List[T] = {
def merge(xs: List[T], ys: List[T]): List[T] =
(xs, ys) match {
case (Nil, _) => ys
case (_, Nil) => xs
case (x :: xs1, y :: ys1) =>
if (less(x, y)) x :: merge(xs1, ys)
else y :: merge(xs, ys1)
}
val n = xs.length/2
if (n == 0) xs
else {
val (ys, zs) = xs splitAt n
merge(msort(less)(ys), msort(less)(zs))
}
}
provoca una StackOverflowError en 5000 listas largas.
¿Hay alguna manera de optimizar esto para que esto no ocurra?
Pensé en tratar de hacerlo recursivo, luego vi mucha información que decía que la JVM no es tan fácil de usar y no siempre optimiza la repetición de cola. ¿Hay algún tipo de directriz para cuando esto tenga éxito? – user44242
La JVM no, por lo que el compilador de Scala lo hará por usted. Solo lo hace bajo ciertos requisitos: debe ser auto-recursión (es decir, f llamando a g, yg llamando a f no funcionará), debe ser _tail_ recursion, por supuesto (la llamada recursiva _must_ siempre será lo último en eso ruta del código), en los métodos debe ser 'final' o' private'. En el ejemplo, porque 'merge' se define dentro de 'msort', en lugar de definirse en una clase u objeto, es efectivamente privado. –
Creo que vale la pena mencionar aquí que el msort en sí mismo no es recursivo de cola, sino fusión. Para cualquiera que solo esté convencido por el compilador, agregue @tailrec a la definición de fusión, y notará que está siendo aceptado como una función recursiva de la cola, tal como lo describió Daniel. –