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
flatMapaninhados + ummapfinal - 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
- Dessugar de for
- Filtrando com if
- Vários geradores
- Usando Option e Future