Desugaring di for
map e flatMap
Desugaring di for è una lezione Scala for Backend Engineering & Functional Programming gratuita su CoddyKit. Questa è la lezione 1 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.
Che cos'è una for-comprehension?
Una for-comprehension in Scala è una sintassi speciale per lavorare con collezioni e altri tipi contenitore. Sembra un ciclo imperativo, ma in realtà è zucchero sintattico che il compilatore riscrive in chiamate a map, flatMap, filter e foreach.
Capire il desugaring aiuta a ragionare su qualsiasi for-comprehension, anche su tipi personalizzati.
object Main {
def main(args: Array[String]): Unit = {
val result = for (x <- List(1, 2, 3)) yield x * 10
println(result)
}
}Un singolo generatore diventa map
Quando una for-comprehension ha esattamente un generatore e usa yield, il compilatore la riscrive in una singola chiamata a map.
for (x <- xs) yield f(x)- diventa
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)
}
}La parola chiave yield
La parola chiave yield indica a Scala di raccogliere i risultati in una nuova collezione dello stesso tipo.
Senza yield, la for-comprehension esegue un effetto collaterale per ogni elemento e restituisce Unit (diventa 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)
}
}Due generatori diventano flatMap + map
Con due o più generatori, quelli esterni diventano flatMap e quello più interno diventa map.
for (x <- xs; y <- ys) yield f(x, y)- diventa
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)
}
}Vedere l'equivalente con flatMap
Qui scriviamo la stessa logica in entrambi i modi. Dimostrare che sono equivalenti mostra che le for-comprehension non aggiungono magia, ma solo leggibilità.
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)
}
}Perché flatMap per il generatore esterno
Ogni elemento esterno produce un'intera collezione di risultati interni. Se usassimo map per il generatore esterno, otterremmo una collezione annidata come List(List(...), List(...)).
flatMap appiattisce queste liste annidate in un unico risultato piatto.
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 senza yield diventa foreach
Un ciclo for senza yield viene riscritto in foreach. Esegue il corpo per i suoi effetti collaterali e produce Unit.
for (x <- xs) doSomething(x)- diventa
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")
}
}Il tipo del risultato segue il primo generatore
Il tipo del risultato è determinato dalla collezione del primo generatore. Un for su una List produce una List; su un Set, un Set; su un Option, un 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)
}
}Associare valori con =
All'interno di una for-comprehension è possibile associare valori intermedi con =. Questo evita di ricalcolare i valori e migliora la leggibilità.
Viene desugared in un map che trasporta il valore aggiuntivo all'interno di una 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)
}
}Funziona con qualsiasi tipo dotato di map/flatMap
Poiché il desugaring si basa solo su map e flatMap, le for-comprehension funzionano con qualsiasi tipo che definisca questi metodi: Option, Either, Try, Future e le Sue classi.
object Main {
def main(args: Array[String]): Unit = {
val combined = for {
a <- Some(2)
b <- Some(3)
} yield a * b
println(combined)
}
}Il vero vantaggio è la leggibilità
Confronti una catena profondamente annidata di flatMap/map con una for-comprehension chiara. Vengono compilate nello stesso modo, ma la versione con for si legge dall'alto verso il basso come una ricetta.
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 rapida
Come desugared dal compilatore una for-comprehension con due generatori e un yield?
Riepilogo
Ha imparato come vengono desugared le for-comprehension:
- Un generatore +
yield→map - Più generatori +
yield→flatMap(esterno) +map(interno) - Nessun
yield→foreachche restituisceUnit - Le associazioni
val =aggiungono valori intermedi - Il tipo del risultato segue il primo generatore
Qualsiasi tipo dotato di map e flatMap può essere usato in una for-comprehension.
Domande Frequenti
La lezione «Desugaring di for» è gratuita?
Sì — il testo completo di «Desugaring di for» è 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 «Desugaring di for»?
map e flatMap 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 1 di 4.
Quanto tempo richiede la lezione «Desugaring di for»?
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