Padrão acumulador
Converta para recursão de cauda.
Padrão acumulador é uma aula grátis de Scala for Backend Engineering & Functional Programming no CoddyKit. Esta é a aula 3 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de Scala for Backend Engineering & Functional Programming, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de Scala for Backend Engineering & Functional Programming inclui 4 aulas no total.
Partes desta aula ainda não foram traduzidas e aparecem em inglês.
The Accumulator Pattern
The accumulator pattern converts a non-tail-recursive function into a tail-recursive one. You carry the partial result in an extra parameter (the accumulator) instead of building it up after the call returns.
The Core Idea
Instead of n + sum(n-1) (work after the call), you compute the new partial total before the call: sum(n-1, acc + n). Now the recursive call is the last action.
Before: Non-Tail Sum
This direct version is not tail-recursive: the addition waits for the recursive call.
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))
}
}After: Tail Sum with Accumulator
Add an acc parameter that holds the running total. The recursive call is now in tail position and can be optimized.
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))
}
}Tail-Recursive Factorial
Apply the same transformation to factorial: multiply into the accumulator before recursing.
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))
}
}Hiding the Accumulator
The extra parameter is an implementation detail. Wrap the tail-recursive worker in a clean public function so callers do not see 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))
}
}Accumulating a List
The pattern also builds collections. A tail-recursive reverse prepends each head to the accumulator list.
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)))
}
}Order of Accumulation
Note that prepending to the accumulator naturally reverses order. For a list-building function that preserves order, you often build reversed and reverse at the end, or use an efficient append structure.
Tail-Recursive map
Build a result list with an accumulator, then reverse once at the end to restore order.
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))
}
}Relation to foldLeft
The accumulator pattern is exactly what foldLeft generalizes: it threads an accumulator through a collection tail-recursively. Many manual accumulator functions can be rewritten as a single foldLeft.
@main def run(): Unit = {
val total = List(1, 2, 3, 4).foldLeft(0)(_ + _)
println(total)
}When to Use It
Reach for the accumulator pattern when a recursive function processes a large linear structure and would otherwise overflow the stack. It trades a slightly less obvious shape for guaranteed stack safety.
Quick Check
Test your grasp of the accumulator pattern.
Recap
You learned the accumulator pattern:
- Carry the partial result in an extra parameter.
- Compute it before recursing to reach tail position.
- Hide the accumulator behind a clean public function.
- It generalizes to
foldLeft.
Perguntas Frequentes
A aula “Padrão acumulador” é grátis?
Sim — o texto completo de “Padrão acumulador” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de Scala for Backend Engineering & Functional Programming, atualize para CoddyKit PRO. O curso de Scala for Backend Engineering & Functional Programming inclui 4 aulas no total.
O que vou aprender em “Padrão acumulador”?
Converta para recursão de cauda. Você pratica Scala for Backend Engineering & Functional Programming com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.
Preciso ter experiência prévia para começar Scala for Backend Engineering & Functional Programming?
Nenhuma experiência prévia é necessária. Scala for Backend Engineering & Functional Programming no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 3 de 4.
Quanto tempo leva a aula “Padrão acumulador”?
A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.
Posso escrever e executar código nesta aula de Scala for Backend Engineering & Functional Programming?
Sim. Cada aula de Scala for Backend Engineering & Functional Programming inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.
Todas as aulas deste curso
- Fundamentos da recursão
- A anotação tailrec
- Padrão acumulador
- Trampolim