0Pricing
Scala for Backend Engineering & Functional Programming · Aula

Dessugar de for

map e flatMap.

Dessugar de for é uma aula grátis de Scala for Backend Engineering & Functional Programming no CoddyKit. Esta é a aula 1 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.

O que é uma compreensão for?

Uma compreensão for no Scala é uma sintaxe especial para trabalhar com coleções e outros tipos de contêiner. Ela se parece com um laço imperativo, mas na verdade é um recurso sintático que o compilador reescreve em chamadas de map, flatMap, filter e foreach.

Entender essa simplificação ajuda você a raciocinar sobre qualquer compreensão for, inclusive sobre tipos personalizados.

object Main {
  def main(args: Array[String]): Unit = {
    val result = for (x <- List(1, 2, 3)) yield x * 10
    println(result)
  }
}

Um único gerador se torna map

Quando uma compreensão for tem exatamente um gerador e usa yield, o compilador a reescreve em uma única chamada de map.

  • for (x <- xs) yield f(x)
  • torna-se xs.map(x => f(x))
object Main {
  def main(args: Array[String]): Unit = {
    val a = for (x <- List(1, 2, 3)) yield x + 1
    val b = List(1, 2, 3).map(x => x + 1)
    println(a == b)
  }
}

A palavra-chave yield

A palavra-chave yield informa ao Scala que deve coletar os resultados em uma nova coleção do mesmo tipo.

Sem yield, a compreensão for executa um efeito colateral para cada elemento e retorna Unit (ela se torna foreach).

object Main {
  def main(args: Array[String]): Unit = {
    // No yield: side effect only
    for (x <- List("a", "b")) println(x)
    // With yield: builds a new List
    val upper = for (x <- List("a", "b")) yield x.toUpperCase
    println(upper)
  }
}

Dois geradores se tornam flatMap + map

Com dois ou mais geradores, os geradores externos se tornam flatMap e o mais interno se torna map.

  • for (x <- xs; y <- ys) yield f(x, y)
  • torna-se xs.flatMap(x => ys.map(y => f(x, y)))
object Main {
  def main(args: Array[String]): Unit = {
    val pairs = for {
      x <- List(1, 2)
      y <- List("a", "b")
    } yield (x, y)
    println(pairs)
  }
}

Vendo o flatMap equivalente

Aqui, escrevemos a mesma lógica das duas formas. Provar que são iguais demonstra que as compreensões for não adicionam mágica, apenas legibilidade.

object Main {
  def main(args: Array[String]): Unit = {
    val sugar = for {
      x <- List(1, 2)
      y <- List(10, 20)
    } yield x + y

    val desugared = List(1, 2).flatMap(x => List(10, 20).map(y => x + y))

    println(sugar)
    println(sugar == desugared)
  }
}

Por que flatMap para o gerador externo

Cada elemento externo produz uma coleção inteira de resultados internos. Se usássemos map para o gerador externo, obteríamos uma coleção aninhada, como List(List(...), List(...)).

flatMap achata essas listas aninhadas em um único resultado plano.

object Main {
  def main(args: Array[String]): Unit = {
    val nested = List(1, 2).map(x => List(10, 20).map(y => x + y))
    val flat   = List(1, 2).flatMap(x => List(10, 20).map(y => x + y))
    println(nested)
    println(flat)
  }
}

for sem yield é foreach

Um laço for sem yield é reescrito em foreach. Ele executa o corpo pelos efeitos colaterais e produz Unit.

  • for (x <- xs) doSomething(x)
  • torna-se xs.foreach(x => doSomething(x))
object Main {
  def main(args: Array[String]): Unit = {
    val r: Unit = for (x <- List(1, 2, 3)) print(x + " ")
    println()
    println("Return type is Unit")
  }
}

O tipo do resultado segue o primeiro gerador

O tipo do resultado é determinado pela coleção do primeiro gerador. Um for sobre uma List produz uma List; sobre um Set, um Set; sobre uma Option, uma Option.

object Main {
  def main(args: Array[String]): Unit = {
    val fromList = for (x <- List(1, 2, 2, 3)) yield x
    val fromSet  = for (x <- Set(1, 2, 2, 3)) yield x
    println(fromList)
    println(fromSet)
  }
}

Vinculando valores com =

Dentro de uma compreensão for, você pode vincular valores intermediários com =. Isso evita recomputações e melhora a legibilidade.

Ela é simplificada para um map que transporta o valor adicional em uma tupla.

object Main {
  def main(args: Array[String]): Unit = {
    val result = for {
      x <- List(1, 2, 3)
      doubled = x * 2
    } yield doubled + 1
    println(result)
  }
}

Funciona com qualquer tipo que tenha map/flatMap

Como a simplificação depende apenas de map e flatMap, as compreensões for funcionam com qualquer tipo que defina esses métodos: Option, Either, Try, Future e suas próprias classes.

object Main {
  def main(args: Array[String]): Unit = {
    val combined = for {
      a <- Some(2)
      b <- Some(3)
    } yield a * b
    println(combined)
  }
}

A verdadeira vantagem é a legibilidade

Compare uma cadeia profundamente aninhada de flatMap/map com uma compreensão for clara. Elas são compiladas para a mesma coisa, mas a versão com for é lida de cima para baixo como uma receita.

object Main {
  def main(args: Array[String]): Unit = {
    val chained = List(1, 2).flatMap(a => List(3, 4).map(b => a * b))
    val readable = for {
      a <- List(1, 2)
      b <- List(3, 4)
    } yield a * b
    println(chained == readable)
  }
}

Verificação rápida

Como o compilador simplifica uma compreensão for com dois geradores e um yield?

Recapitulação

Você aprendeu como as compreensões for são simplificadas:

  • Um gerador + yield → map
  • Vários geradores + yield → flatMap (externo) + map (interno)
  • Sem yield → foreach retornando Unit
  • Vinculações val = adicionam valores intermediários
  • O tipo do resultado segue o primeiro gerador

Qualquer tipo com map e flatMap pode ser usado em uma compreensão for.

Perguntas Frequentes

A aula “Dessugar de for” é grátis?

Sim — o texto completo de “Dessugar de for” é 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 “Dessugar de for”?

map e flatMap. 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 1 de 4.

Quanto tempo leva a aula “Dessugar de for”?

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. Dessugar de for
  2. Filtrando com if
  3. Vários geradores
  4. Usando Option e Future
← Voltar para Scala for Backend Engineering & Functional Programming