0Pricing
Scala for Backend Engineering & Functional Programming · Lección

Patrón acumulador

Convierta a recursión de cola

Patrón acumulador es una lección gratuita de Scala for Backend Engineering & Functional Programming en CoddyKit. Esta es la lección 3 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de Scala for Backend Engineering & Functional Programming, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de Scala for Backend Engineering & Functional Programming incluye 4 lecciones en total.

El patrón del acumulador

El patrón del acumulador convierte una función que no es recursiva de cola en una función recursiva de cola. Se conserva el resultado parcial en un parámetro adicional (el acumulador) en lugar de construirlo después de que la llamada devuelva el resultado.

La idea central

En lugar de n + sum(n-1) (trabajo posterior a la llamada), se calcula el nuevo total parcial antes de la llamada: sum(n-1, acc + n). Ahora la llamada recursiva es la última acción.

Antes: suma no recursiva de cola

Esta versión directa no es recursiva de cola: la suma espera a que termine la llamada recursiva.

object Main {
  def sum(n: Int): Int =
    if (n == 0) 0 else n + sum(n - 1)

  def main(args: Array[String]): Unit = {
    println(sum(50))
  }
}

Después: suma de cola con acumulador

Añada un parámetro acc que contenga el total acumulado. La llamada recursiva está ahora en posición de cola y puede optimizarse.

import scala.annotation.tailrec

object Main {
  @tailrec
  def sum(n: Int, acc: Int = 0): Int =
    if (n == 0) acc else sum(n - 1, acc + n)

  def main(args: Array[String]): Unit = {
    println(sum(50))
  }
}

Factorial recursivo de cola

Aplique la misma transformación al factorial: multiplique el acumulador antes de volver a llamar a la función.

import scala.annotation.tailrec

object Main {
  @tailrec
  def factorial(n: Int, acc: Long = 1): Long =
    if (n <= 1) acc else factorial(n - 1, acc * n)

  def main(args: Array[String]): Unit = {
    println(factorial(10))
  }
}

Ocultar el acumulador

El parámetro adicional es un detalle de implementación. Envuelva la función auxiliar recursiva de cola en una función pública clara para que quienes la llamen no vean acc.

import scala.annotation.tailrec

object Main {
  def factorial(n: Int): Long = {
    @tailrec
    def loop(m: Int, acc: Long): Long =
      if (m <= 1) acc else loop(m - 1, acc * m)
    loop(n, 1)
  }

  def main(args: Array[String]): Unit = {
    println(factorial(6))
  }
}

Acumular una lista

El patrón también permite construir colecciones. Una inversión recursiva de cola antepone cada cabeza al acumulador.

import scala.annotation.tailrec

object Main {
  def reverse[A](xs: List[A]): List[A] = {
    @tailrec
    def loop(rem: List[A], acc: List[A]): List[A] = rem match {
      case Nil    => acc
      case h :: t => loop(t, h :: acc)
    }
    loop(xs, Nil)
  }

  def main(args: Array[String]): Unit = {
    println(reverse(List(1, 2, 3, 4)))
  }
}

Orden de acumulación

Observe que anteponer elementos al acumulador invierte el orden de forma natural. Para una función que construya una lista conservando el orden, normalmente se construye la lista invertida y se invierte al final, o se utiliza una estructura de adición eficiente.

map recursivo de cola

Construya una lista de resultados con un acumulador y, después, inviértala una sola vez al final para restaurar el orden.

import scala.annotation.tailrec

object Main {
  def mapTail[A, B](xs: List[A])(f: A => B): List[B] = {
    @tailrec
    def loop(rem: List[A], acc: List[B]): List[B] = rem match {
      case Nil    => acc.reverse
      case h :: t => loop(t, f(h) :: acc)
    }
    loop(xs, Nil)
  }

  def main(args: Array[String]): Unit = {
    println(mapTail(List(1, 2, 3))(_ * 10))
  }
}

Relación con foldLeft

El patrón del acumulador es exactamente lo que generaliza foldLeft: pasa un acumulador por una colección mediante recursión de cola. Muchas funciones manuales con acumuladores pueden reescribirse como un único foldLeft.

@main def run(): Unit = {
  val total = List(1, 2, 3, 4).foldLeft(0)(_ + _)
  println(total)
}

Cuándo utilizarlo

Recurra al patrón del acumulador cuando una función recursiva procese una estructura lineal grande y, de otro modo, pudiera desbordar la pila. A cambio de una estructura algo menos evidente, ofrece seguridad garantizada frente al desbordamiento de pila.

Comprobación rápida

Compruebe su dominio del patrón del acumulador.

Resumen

Ha aprendido el patrón del acumulador:

  • Conserve el resultado parcial en un parámetro adicional.
  • Calcúlelo antes de recursar para alcanzar la posición de cola.
  • Oculte el acumulador detrás de una función pública clara.
  • Se generaliza mediante foldLeft.

Preguntas frecuentes

¿La lección «Patrón acumulador» es gratis?

Sí — el texto completo de «Patrón acumulador» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de Scala for Backend Engineering & Functional Programming, actualiza a CoddyKit PRO. El curso de Scala for Backend Engineering & Functional Programming incluye 4 lecciones en total.

¿Qué aprenderé en «Patrón acumulador»?

Convierta a recursión de cola Practicas Scala for Backend Engineering & Functional Programming con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.

¿Necesito experiencia previa para empezar Scala for Backend Engineering & Functional Programming?

No se requiere experiencia previa. Scala for Backend Engineering & Functional Programming en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 3 de 4.

¿Cuánto tiempo toma la lección «Patrón acumulador»?

La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.

¿Puedo escribir y ejecutar código en esta lección de Scala for Backend Engineering & Functional Programming?

Sí. Cada lección de Scala for Backend Engineering & Functional Programming incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.

Todas las lecciones de este curso

  1. Conceptos básicos de recursión
  2. La anotación tailrec
  3. Patrón acumulador
  4. Trampolining
← Volver a Scala for Backend Engineering & Functional Programming