0Pricing
Scala for Backend Engineering & Functional Programming · Lezione

Usare Option e Future

Concatenazione monadica

Usare Option e Future è una lezione Scala for Backend Engineering & Functional Programming gratuita su CoddyKit. Questa è la lezione 4 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.

Oltre le collection

Le for-comprehension non sono limitate alle liste. È possibile usare qualsiasi tipo che fornisca map e flatMap, inclusi Option, Either, Try e Future. Questa tecnica si chiama concatenamento monadico.

object Main {
  def main(args: Array[String]): Unit = {
    val sum = for {
      a <- Some(10)
      b <- Some(20)
    } yield a + b
    println(sum)
  }
}

Option interrompe l'elaborazione con None

Con Option, la comprehension produce un risultato solo se ogni generatore è Some. Se uno qualsiasi è None, l'intero risultato è None e i passaggi successivi vengono saltati.

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

    val missing = for {
      a <- Some(2)
      b <- None: Option[Int]
    } yield a * b

    println(ok)
    println(missing)
  }
}

Concatenare ricerche opzionali

Un modello comune consiste nel cercare chiavi in una Map, dove ogni ricerca restituisce un Option. La for-comprehension produce un valore solo se tutte le ricerche hanno esito positivo.

object Main {
  def main(args: Array[String]): Unit = {
    val prices = Map("apple" -> 3, "bread" -> 5)
    val total = for {
      a <- prices.get("apple")
      b <- prices.get("bread")
    } yield a + b
    println(total)

    val missing = for {
      a <- prices.get("apple")
      c <- prices.get("milk")
    } yield a + c
    println(missing)
  }
}

Perché è meglio degli if-else annidati

Senza le for-comprehension dovrebbe annidare i pattern match o i controlli sui valori null. La forma monadica appiattisce quella piramide in una sequenza lineare e pulita.

object Main {
  def parse(s: String): Option[Int] = s.toIntOption
  def main(args: Array[String]): Unit = {
    val result = for {
      x <- parse("40")
      y <- parse("2")
    } yield x + y
    println(result)
  }
}

Le guardie funzionano anche con Option

Una guardia all'interno di una comprehension su Option trasforma un valore in None quando la condizione non è soddisfatta, agendo come una validazione inline.

object Main {
  def main(args: Array[String]): Unit = {
    def validate(age: Int): Option[Int] =
      for {
        a <- Some(age)
        if a >= 18
      } yield a
    println(validate(25))
    println(validate(15))
  }
}

Introduzione a Future

Un Future rappresenta un valore che sarà disponibile in seguito. Come Option, dispone di map e flatMap, quindi le for-comprehension possono mettere in sequenza passaggi asincroni.

import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Await
import scala.concurrent.duration._

object Main {
  def main(args: Array[String]): Unit = {
    val f = for {
      a <- Future(10)
      b <- Future(20)
    } yield a + b
    println(Await.result(f, 2.seconds))
  }
}

Qui i Future vengono eseguiti in sequenza

Quando un generatore dipende da un altro all'interno di una for-comprehension, i future vengono eseguiti in sequenza, perché ogni flatMap attende il risultato precedente.

import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Await
import scala.concurrent.duration._

object Main {
  def main(args: Array[String]): Unit = {
    val f = for {
      a <- Future(5)
      b <- Future(a * 2)
    } yield a + b
    println(Await.result(f, 2.seconds))
  }
}

Eseguire i future in parallelo

Per eseguire i future in parallelo, li avvii prima della for-comprehension e poi li combini. Le attività indipendenti si sovrappongono invece di attendere.

import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Await
import scala.concurrent.duration._

object Main {
  def main(args: Array[String]): Unit = {
    val fa = Future(100)
    val fb = Future(200)
    val combined = for {
      a <- fa
      b <- fb
    } yield a + b
    println(Await.result(combined, 2.seconds))
  }
}

Either per errori più ricchi

Either[E, A] contiene un valore di errore in caso di fallimento. In una for-comprehension, il primo Left interrompe l'elaborazione e viene restituito.

object Main {
  def parse(s: String): Either[String, Int] =
    s.toIntOption.toRight(s"not a number: $s")
  def main(args: Array[String]): Unit = {
    val good = for { a <- parse("3"); b <- parse("4") } yield a + b
    val bad  = for { a <- parse("3"); b <- parse("x") } yield a + b
    println(good)
    println(bad)
  }
}

La stessa struttura per molti tipi

Noti che la comprehension ha un aspetto identico sia con Option, Either, Try sia con Future. Cambia solo la semantica del fallimento. Questa uniformità è la forza del concatenamento monadico.

import scala.util.Try

object Main {
  def main(args: Array[String]): Unit = {
    val result = for {
      a <- Try("21".toInt)
      b <- Try("2".toInt)
    } yield a * b
    println(result)
  }
}

Non è consentito combinare tipi diversi

Tutti i generatori di una comprehension devono appartenere alla stessa monade. Non può combinare direttamente un generatore Option con un generatore Future; prima deve convertire uno dei due, ad esempio con Future.fromTry, oppure racchiudere l'Option.

object Main {
  def main(args: Array[String]): Unit = {
    // Convert the Option to keep types consistent
    val maybe: Option[Int] = Some(7)
    val result = for {
      a <- maybe
      b <- maybe.map(_ + 1)
    } yield a + b
    println(result)
  }
}

Verifica rapida

In una for-comprehension su Option, cosa succede se un generatore produce None?

Riepilogo

Ha imparato il concatenamento monadico con le for-comprehension:

  • Funziona con qualsiasi tipo che disponga di map e flatMap
  • Option interrompe l'elaborazione con None
  • Either e Try interrompono l'elaborazione in caso di fallimento, conservando le informazioni sull'errore
  • Future mette in sequenza i passaggi asincroni; li avvii in anticipo per ottenere il parallelismo
  • Tutti i generatori devono condividere lo stesso tipo di monade

Domande Frequenti

La lezione «Usare Option e Future» è gratuita?

Sì — il testo completo di «Usare Option e Future» è 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 «Usare Option e Future»?

Concatenazione monadica 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 4 di 4.

Quanto tempo richiede la lezione «Usare Option e Future»?

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

  1. Desugaring di for
  2. Filtrare con if
  3. Generatori multipli
  4. Usare Option e Future
← Torna a Scala for Backend Engineering & Functional Programming