Generatori multipli
Iterazione annidata
Generatori multipli è una lezione Scala for Backend Engineering & Functional Programming gratuita su CoddyKit. Questa è la lezione 3 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento Scala for Backend Engineering & Functional Programming, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso Scala for Backend Engineering & Functional Programming include 4 lezioni in totale.
L'iterazione annidata diventa lineare
Una for-comprehension può contenere diversi generatori. Ognuno è una riga <- che itera su una collection. Insieme producono ogni combinazione possibile: una sorta di ciclo annidato scritto in forma lineare.
object Main {
def main(args: Array[String]): Unit = {
val pairs = for {
x <- List(1, 2)
y <- List('a', 'b')
} yield (x, y)
println(pairs)
}
}È un prodotto cartesiano
Due generatori di dimensioni m e n producono m × n risultati, cioè l'intero prodotto cartesiano. Il primo generatore è il ciclo esterno, il secondo quello 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(", "))
}
}Il generatore interno può dipendere da quello esterno
Un generatore successivo può usare i valori associati dai generatori precedenti. Questo non è possibile con un semplice prodotto cartesiano ed è uno dei motivi per cui le for-comprehension sono così flessibili.
object Main {
def main(args: Array[String]): Unit = {
val upperTriangle = for {
i <- 1 to 4
j <- i to 4
} yield (i, j)
println(upperTriangle)
}
}Tre o più generatori
Può concatenare tutti i generatori che desidera. Con tre generatori ottiene un ciclo annidato su tre livelli, che produce tuple o valori calcolati.
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)
}
}Il classico esempio pitagorico
Un uso famoso consiste nel trovare le terne pitagoriche. Iteriamo su tre numeri e conserviamo solo quelli per cui a*a + b*b == c*c, combinando più generatori con una guardia.
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)
}
}Come viene desugared
Più generatori diventano chiamate flatMap annidate con un map finale:
xs.flatMap(x => ys.flatMap(y => zs.map(z => ...)))
Ogni generatore aggiuntivo aggiunge un ulteriore livello di annidamento.
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)
}
}Combinare generatori e guardie
Può alternare liberamente generatori e guardie. Una guardia inserita tra due generatori elimina i valori esterni prima ancora che venga eseguito il ciclo interno.
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)
}
}Appiattire collection annidate
Quando ha una collection di collection, due generatori la appiattiscono naturalmente: il primo itera su quella esterna, il secondo su ciascuna collection 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)
}
}Costruire una griglia di stringhe
Più generatori sono ideali per generare output strutturati, come coordinate o una tabella pitagorica.
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"))
}
}Combinare collection di dimensioni diverse
I generatori non devono avere necessariamente la stessa lunghezza. Viene prodotta ogni combinazione formata da un elemento di ciascuno.
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)
}
}L'ordine influisce sulla sequenza di output
Scambiare l'ordine dei generatori mantiene lo stesso insieme di combinazioni, ma ne cambia l'ordine, perché l'ultimo generatore varia più 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 rapida
Quante tuple produce for { x <- List(1,2,3); y <- List('a','b') } yield (x, y)?
Riepilogo
Ha imparato a usare più generatori:
- Ogni riga
<-aggiunge un livello di iterazione annidata - Insieme producono il prodotto cartesiano
- I generatori interni possono dipendere dai valori associati da quelli esterni
- Vengono desugared in
flatMapannidati più unmapfinale - L'ordine dei generatori modifica l'ordine dei risultati
Domande Frequenti
La lezione «Generatori multipli» è gratuita?
Sì — il testo completo di «Generatori multipli» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso Scala for Backend Engineering & Functional Programming, passa a CoddyKit PRO. Il corso Scala for Backend Engineering & Functional Programming include 4 lezioni in totale.
Cosa imparerò in «Generatori multipli»?
Iterazione annidata Eserciti Scala for Backend Engineering & Functional Programming con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.
Ho bisogno di esperienza per iniziare Scala for Backend Engineering & Functional Programming?
Non è richiesta alcuna esperienza precedente. Scala for Backend Engineering & Functional Programming su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 3 di 4.
Quanto tempo richiede la lezione «Generatori multipli»?
La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.
Posso scrivere ed eseguire codice in questa lezione Scala for Backend Engineering & Functional Programming?
Sì. Ogni lezione Scala for Backend Engineering & Functional Programming include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.
Tutte le lezioni di questo corso
- Desugaring di for
- Filtrare con if
- Generatori multipli
- Usare Option e Future