Scala for Backend Engineering & Functional Programming · Aula

Folding e redução

foldLeft e reduce.

Aula 3 de 413 etapas

Folding e redução é 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.

Combinando elementos em um só

Às vezes, você precisa combinar todos os elementos de uma coleção em um único valor, como uma soma ou concatenação. Scala oferece fold, foldLeft, foldRight e reduce para isso.

object Main {
  def main(args: Array[String]): Unit = {
    val nums = List(1, 2, 3, 4)
    println(nums.sum)
    println(nums.product)
  }
}

reduce: combinando sem uma semente

reduce combina elementos aos pares usando uma função binária. Ele precisa de pelo menos um elemento; caso contrário, lança uma exceção.

object Main {
  def main(args: Array[String]): Unit = {
    val nums = List(1, 2, 3, 4)
    val total = nums.reduce((a, b) => a + b)
    println(total)
    val max = nums.reduce((a, b) => if (a > b) a else b)
    println(max)
  }
}

foldLeft: combinando com uma semente

foldLeft recebe um valor de semente inicial e uma função. Ele é seguro em coleções vazias (retorna a semente) e permite que o tipo do resultado seja diferente do tipo dos elementos.

Sintaxe: xs.foldLeft(seed)((acc, x) => ...).

object Main {
  def main(args: Array[String]): Unit = {
    val nums = List(1, 2, 3, 4)
    val sum = nums.foldLeft(0)((acc, x) => acc + x)
    println(sum)
    val empty = List.empty[Int].foldLeft(0)(_ + _)
    println(empty)
  }
}

O padrão do acumulador

Em um fold, o primeiro argumento é o acumulador que carrega o resultado em andamento, e o segundo é o elemento atual. Cada etapa atualiza o acumulador.

object Main {
  def main(args: Array[String]): Unit = {
    val words = List("Scala", "is", "great")
    val sentence = words.foldLeft("")((acc, w) => acc + w + " ")
    println(sentence.trim)
  }
}

O tipo do resultado pode ser diferente

Uma característica poderosa de foldLeft: o tipo do acumulador pode ser diferente do tipo dos elementos. Aqui, dobramos uma lista de números em uma String.

object Main {
  def main(args: Array[String]): Unit = {
    val nums = List(1, 2, 3)
    val joined = nums.foldLeft("nums:")((acc, n) => acc + " " + n)
    println(joined)
  }
}

foldRight: da direita

foldRight processa os elementos da direita para a esquerda. O acumulador é o segundo argumento: (x, acc) => .... A direção é importante para operações não comutativas.

object Main {
  def main(args: Array[String]): Unit = {
    val nums = List(1, 2, 3, 4)
    val left = nums.foldLeft("")((acc, x) => acc + x)
    val right = nums.foldRight("")((x, acc) => acc + x)
    println("foldLeft:  " + left)
    println("foldRight: " + right)
  }
}

Esquerda versus direita e desempenho

foldLeft é recursivo em cauda e não causa estouro da pilha em listas grandes. foldRight em uma List pode causar estouro da pilha para entradas muito grandes. Prefira foldLeft, a menos que a ordem exija o contrário.

object Main {
  def main(args: Array[String]): Unit = {
    val big = (1 to 100000).toList
    val total = big.foldLeft(0L)((acc, x) => acc + x)
    println(total)
  }
}

Construindo uma coleção com fold

As dobras são suficientemente gerais para construir coleções. Aqui, invertemos uma lista adicionando cada elemento no início de uma lista acumuladora.

object Main {
  def main(args: Array[String]): Unit = {
    val nums = List(1, 2, 3, 4)
    val reversed = nums.foldLeft(List.empty[Int])((acc, x) => x :: acc)
    println(reversed)
  }
}

reduceOption para maior segurança

Como reduce falha em coleções vazias, reduceOption retorna um Option: Some(result) quando não está vazio e None quando está vazio.

object Main {
  def main(args: Array[String]): Unit = {
    println(List(3, 1, 4).reduceOption(_ + _))
    println(List.empty[Int].reduceOption(_ + _))
  }
}

fold: uma variante simétrica

fold é semelhante a foldLeft, mas o acumulador deve ser do mesmo tipo que os elementos. Ele é frequentemente usado com coleções paralelas.

object Main {
  def main(args: Array[String]): Unit = {
    val nums = List(1, 2, 3, 4)
    val total = nums.fold(0)(_ + _)
    println(total)
  }
}

Contando com foldLeft

As dobras podem calcular resultados mais elaborados, como contar quantos elementos satisfazem uma condição, tudo em uma única passagem.

object Main {
  def main(args: Array[String]): Unit = {
    val nums = List(4, 7, 2, 9, 6, 1)
    val evenCount = nums.foldLeft(0)((acc, x) => if (x % 2 == 0) acc + 1 else acc)
    println(s"even numbers: $evenCount")
  }
}

Verificação rápida

Qual é a principal diferença entre reduce e foldLeft?

Recapitulação

Você aprendeu sobre dobras e reduções:

  • reduce — combina elementos aos pares, sem valor inicial, e falha se estiver vazio
  • reduceOption — variante segura que retorna Option
  • foldLeft — valor inicial + acumulador, seguro para a pilha, com tipo de resultado flexível
  • foldRight — da direita para a esquerda; atenção à pilha em listas grandes
  • As dobras também podem construir novas coleções
Grátis para começar

Aprenda Scala com um tutor de IA — grátis

Escreva e execute código real no seu navegador, obtenha ajuda instantânea de um tutor de IA 24/7 e continue de onde parou na web ou no app.

Cursos
39
Aulas
143

Perguntas Frequentes

A aula “Folding e redução” é grátis?

Sim — o texto completo de “Folding e redução” é 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 “Folding e redução”?

foldLeft e reduce. 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 “Folding e redução”?

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. List, Vector, Set, Map
  2. Transformações
  3. Folding e redução
  4. Agrupamento e ordenação
← Voltar para Scala for Backend Engineering & Functional Programming