0Pricing
Scala for Backend Engineering & Functional Programming · Aula

Vários geradores

Iteração aninhada.

Vários geradores é 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.

Iteração aninhada em formato linear

Uma compreensão for pode ter vários geradores. Cada um é uma linha com <- que itera sobre uma coleção. Juntos, eles produzem todas as combinações, como um laço aninhado escrito de forma linear.

object Main {
  def main(args: Array[String]): Unit = {
    val pairs = for {
      x <- List(1, 2)
      y <- List('a', 'b')
    } yield (x, y)
    println(pairs)
  }
}

É um produto cartesiano

Dois geradores de tamanhos m e n produzem m × n resultados, o produto cartesiano completo. O primeiro gerador é o laço externo, e o segundo é o laço interno.

object Main {
  def main(args: Array[String]): Unit = {
    val grid = for {
      row <- 1 to 3
      col <- 1 to 3
    } yield s"r$row-c$col"
    println(grid.mkString(", "))
  }
}

O gerador interno pode depender do externo

Um gerador posterior pode usar valores vinculados pelos geradores anteriores. Isso é impossível com um produto cartesiano simples e é uma das razões pelas quais as compreensões for são tão flexíveis.

object Main {
  def main(args: Array[String]): Unit = {
    val upperTriangle = for {
      i <- 1 to 4
      j <- i to 4
    } yield (i, j)
    println(upperTriangle)
  }
}

Três ou mais geradores

Você pode empilhar quantos geradores quiser. Com três geradores, você obtém um laço triplo aninhado, produzindo tuplas ou valores calculados.

object Main {
  def main(args: Array[String]): Unit = {
    val triples = for {
      a <- 1 to 2
      b <- 1 to 2
      c <- 1 to 2
    } yield (a, b, c)
    println(triples.size + " combinations")
    triples.foreach(println)
  }
}

O exemplo clássico de Pitágoras

Um uso famoso: encontrar ternas pitagóricas. Iteramos três números e mantemos apenas aqueles em que a*a + b*b == c*c, combinando vários geradores com uma guarda.

object Main {
  def main(args: Array[String]): Unit = {
    val triples = for {
      a <- 1 to 20
      b <- a to 20
      c <- b to 20
      if a * a + b * b == c * c
    } yield (a, b, c)
    triples.foreach(println)
  }
}

Como isso é desfeito sintaticamente

Vários geradores se tornam chamadas aninhadas de flatMap com um map final:

  • xs.flatMap(x => ys.flatMap(y => zs.map(z => ...)))

Cada gerador adicional acrescenta mais um nível de aninhamento.

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

Combinando geradores e guardas

Você pode intercalar geradores e guardas livremente. Uma guarda posicionada entre dois geradores elimina valores externos antes mesmo que o laço interno seja executado.

object Main {
  def main(args: Array[String]): Unit = {
    val result = for {
      x <- 1 to 5
      if x % 2 == 1
      y <- 1 to 5
      if y > x
    } yield (x, y)
    println(result)
  }
}

Nivelando coleções aninhadas

Quando você tem uma coleção de coleções, dois geradores a nivelam naturalmente: o primeiro itera sobre a coleção externa, e o segundo itera sobre cada coleção interna.

object Main {
  def main(args: Array[String]): Unit = {
    val matrix = List(List(1, 2), List(3, 4), List(5, 6))
    val flat = for {
      row <- matrix
      value <- row
    } yield value
    println(flat)
  }
}

Construindo uma grade de textos

Vários geradores são excelentes para gerar saídas estruturadas, como coordenadas ou uma tabuada.

object Main {
  def main(args: Array[String]): Unit = {
    val table = for {
      i <- 1 to 3
      j <- 1 to 3
    } yield s"$i*$j=${i * j}"
    println(table.grouped(3).map(_.mkString("  ")).mkString("\n"))
  }
}

Combinando coleções de tamanhos diferentes

Os geradores não precisam ter o mesmo tamanho. Cada combinação de um elemento de cada coleção é produzida.

object Main {
  def main(args: Array[String]): Unit = {
    val sizes = List("S", "M", "L")
    val colors = List("red", "blue")
    val products = for {
      s <- sizes
      c <- colors
    } yield s"$c-$s"
    println(products)
  }
}

A ordem afeta a sequência de saída

Trocar a ordem dos geradores mantém o mesmo conjunto de combinações, mas altera a ordem delas, porque o último gerador varia mais rapidamente.

object Main {
  def main(args: Array[String]): Unit = {
    val ab = for { x <- List(1, 2); y <- List(9, 8) } yield (x, y)
    val ba = for { y <- List(9, 8); x <- List(1, 2) } yield (x, y)
    println(ab)
    println(ba)
  }
}

Verificação rápida

Quantas tuplas for { x <- List(1,2,3); y <- List('a','b') } yield (x, y) produz?

Recapitulação

Você aprendeu sobre vários geradores:

  • Cada linha com <- acrescenta um nível de iteração aninhada
  • Juntos, eles produzem o produto cartesiano
  • Os geradores internos podem depender dos valores associados pelos geradores externos
  • Eles são transformados sintaticamente em flatMap aninhados + um map final
  • A ordem dos geradores altera a ordenação do resultado

Perguntas Frequentes

A aula “Vários geradores” é grátis?

Sim — o texto completo de “Vários geradores” é 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 “Vários geradores”?

Iteração aninhada. 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 “Vários geradores”?

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