0Pricing
Scala for Backend Engineering & Functional Programming · Aula

foldLeft e foldRight

Reduza coleções a um valor.

foldLeft e foldRight é 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.

Dobrando uma coleção

A dobra reduz uma coleção a um único valor, combinando repetidamente os elementos com um acumulador.

O padrão de acumulador que você aprendeu é exatamente o que fold abstrai. Em vez de escrever a função auxiliar recursiva, você fornece um valor inicial e uma função de combinação.

Fundamentos de foldLeft

foldLeft recebe um acumulador inicial e uma função (acc, element) e percorre a coleção da esquerda para a direita.

A cada etapa, ele substitui o acumulador pelo resultado da função.

val xs = List(1, 2, 3, 4)
val total = xs.foldLeft(0)((acc, x) => acc + x)

@main def run(): Unit =
  println(total)  // 10

Como foldLeft associa

foldLeft agrupa a partir da esquerda. Para List(1, 2, 3) com a semente z, ele calcula f(f(f(z, 1), 2), 3).

O acumulador é o argumento esquerdo, portanto acumula à medida que você avança para a direita pela lista.

// List(1, 2, 3).foldLeft(0)(_ + _)
// = ((0 + 1) + 2) + 3
// = 6

Fundamentos de foldRight

foldRight também combina elementos, mas começa pela direita.

Sua função recebe (element, acc), com o elemento à esquerda e o acumulador à direita.

val xs = List(1, 2, 3, 4)
val total = xs.foldRight(0)((x, acc) => x + acc)

@main def run(): Unit =
  println(total)  // 10

Como foldRight associa

foldRight agrupa a partir da direita. Para List(1, 2, 3) com a semente z, ele calcula f(1, f(2, f(3, z))).

A semente fica na extremidade direita, e a lista é combinada para dentro a partir do final.

// List(1, 2, 3).foldRight(0)(_ + _)
// = 1 + (2 + (3 + 0))
// = 6

Quando a direção importa

Para operações associativas e comutativas, como soma ou produto, as duas dobras produzem a mesma resposta.

Para operações não comutativas, como subtração ou construção de listas, a direção altera o resultado. Escolha conscientemente.

val xs = List(1, 2, 3)
val l = xs.foldLeft(0)(_ - _)   // ((0-1)-2)-3 = -6
val r = xs.foldRight(0)(_ - _)  // 1-(2-(3-0)) = 2

@main def run(): Unit =
  println((l, r))  // (-6, 2)

Construindo uma lista

foldRight é a escolha natural para reconstruir uma lista na ordem, porque trabalha da cauda para dentro e adicionar elementos no início os mantém no lugar.

Isso transforma cada elemento preservando a ordem.

val xs = List(1, 2, 3)
val doubled = xs.foldRight(List.empty[Int]) { (x, acc) =>
  (x * 2) :: acc
}

@main def run(): Unit =
  println(doubled)  // List(2, 4, 6)

foldLeft inverte

Se você construir uma lista com foldLeft e adicionar elementos no início, o resultado ficará invertido, porque os elementos são adicionados primeiro à frente à medida que você avança para a direita.

Às vezes, isso é exatamente o que você deseja.

val xs = List(1, 2, 3)
val rev = xs.foldLeft(List.empty[Int]) { (acc, x) =>
  x :: acc
}

@main def run(): Unit =
  println(rev)  // List(3, 2, 1)

Segurança da pilha

foldLeft é recursivo de cauda e executado como um laço, portanto é seguro em coleções enormes.

foldRight em uma List não é recursivo de cauda e pode causar estouro da pilha em listas muito longas. Prefira foldLeft quando não precisar da ordem da direita para a esquerda.

// Safe even for millions of elements:
val n = (1 to 1000000).foldLeft(0L)(_ + _)

// foldRight on a long List risks StackOverflowError

Alterando o tipo do resultado

O tipo do acumulador pode ser diferente do tipo dos elementos.

Aqui, dobramos uma lista de inteiros em uma string, portanto a semente é uma string vazia e cada etapa adiciona conteúdo ao final.

O tipo da dobra é determinado pela semente.

val xs = List(1, 2, 3)
val s = xs.foldLeft("")((acc, x) => acc + x.toString)

@main def run(): Unit =
  println(s)  // "123"

A dobra como ferramenta versátil

Muitas operações de lista são casos especiais de fold: sum, produto, tamanho, max, map, filtragem, reverse.

Reconhecer a operação de fold subjacente ajuda você a escrever código conciso e declarativo em vez de recursão criada manualmente.

val xs = List(4, 1, 7, 3)
val maxV = xs.foldLeft(Int.MinValue)(_ max _)
val len  = xs.foldLeft(0)((acc, _) => acc + 1)

@main def run(): Unit =
  println((maxV, len))  // (7, 4)

Verificação rápida

Raciocine sobre a direção da dobra e a posição da semente.

Recapitulação

foldLeft percorre da esquerda para a direita, com o acumulador à esquerda, e calcula ((z op a) op b) op c. Ele é recursivo de cauda e seguro para a pilha.

foldRight percorre da direita para a esquerda, com a semente à direita, e calcula a op (b op (c op z)). É adequado para construir listas preservando a ordem, mas pode causar estouro em listas longas.

A semente determina o tipo do resultado, portanto as dobras podem transformar uma coleção em qualquer valor.

Perguntas Frequentes

A aula “foldLeft e foldRight” é grátis?

Sim — o texto completo de “foldLeft e foldRight” é 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 “foldLeft e foldRight”?

Reduza coleções a um valor. 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 “foldLeft e foldRight”?

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

  1. Pensando recursivamente
  2. Padrões de acumuladores
  3. foldLeft e foldRight
  4. reduce e agregação
← Voltar para Scala for Backend Engineering & Functional Programming