0Pricing
Scala for Backend Engineering & Functional Programming · Lezione

Corrispondenza esaustiva

Completezza verificata dal compilatore

Corrispondenza esaustiva è 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.

Che cos'è il matching esaustivo?

Un match è esaustivo quando gestisce ogni possibile valore del tipo sottoposto a matching.

Per un trait sealed, il compilatore conosce tutte le varianti e può verificare che il match le copra tutte.

Un match completo

Quando gestisce ogni variante di un trait sealed, il compilatore non segnala problemi e non compare alcun avviso.

sealed trait Color
case object Red extends Color
case object Green extends Color
case object Blue extends Color
object Main {
  def name(c: Color): String = c match {
    case Red   => "red"
    case Green => "green"
    case Blue  => "blue"
  }
  def main(args: Array[String]): Unit = {
    println(name(Blue))
  }
}

Il compilatore veglia su di Lei

Se omette una variante, il compilatore emette un avviso di match non esaustivo in fase di compilazione.

È una rete di sicurezza: scopre il problema prima di eseguire il programma.

Aggiungere in seguito una variante

Il vero vantaggio si vede quando aggiunge una nuova variante. Ogni match non esaustivo nella codebase genera un avviso, ricordandoLe di gestire il nuovo caso.

Questo rende il refactoring sicuro e prevedibile.

Perché evitare un carattere jolly

Aggiungere case _ => elimina gli avvisi sull'esaustività. In seguito, quando aggiunge varianti, potrebbe però nascondere dei bug.

Per gli ADT sealed, preferisca elencare esplicitamente ogni variante, così il compilatore continuerà a proteggerLa.

sealed trait Status
case object Active extends Status
case object Inactive extends Status
object Main {
  def label(s: Status): String = s match {
    case Active   => "on"
    case Inactive => "off"
  }
  def main(args: Array[String]): Unit = {
    println(label(Active))
  }
}

Esaustività con i dati

L'esaustività si applica anche alle varianti che contengono dati. Associa i campi e deve comunque coprire ogni variante.

sealed trait Shape
case class Circle(r: Double) extends Shape
case class Square(s: Double) extends Shape
object Main {
  def area(sh: Shape): Double = sh match {
    case Circle(r) => 3.14159 * r * r
    case Square(s) => s * s
  }
  def main(args: Array[String]): Unit = {
    println(area(Circle(2)))
    println(area(Square(3)))
  }
}

Combinare il matching con le guardie

Faccia attenzione: le guardie possono rendere un match non esaustivo, perché il compilatore non può dimostrare che coprano tutti i valori.

Fornisca un caso finale senza guardia per la stessa variante, in modo da mantenere l'esaustività.

sealed trait Temp
case class Celsius(v: Int) extends Temp
object Main {
  def feel(t: Temp): String = t match {
    case Celsius(v) if v >= 30 => "hot"
    case Celsius(v)            => "not hot"
  }
  def main(args: Array[String]): Unit = {
    println(feel(Celsius(35)))
    println(feel(Celsius(10)))
  }
}

Esaustività con Option

Option della libreria standard è un ADT sealed con Some e None. Eseguire il matching su entrambi rende il match esaustivo.

object Main {
  def show(o: Option[Int]): String = o match {
    case Some(v) => s"value $v"
    case None    => "nothing"
  }
  def main(args: Array[String]): Unit = {
    println(show(Some(7)))
    println(show(None))
  }
}

Esaustività annidata

L'esaustività è utile anche con ADT annidati. Il compilatore ragiona su ogni livello destrutturato.

sealed trait Tree
case object Leaf extends Tree
case class Node(v: Int, l: Tree, r: Tree) extends Tree
object Main {
  def depth(t: Tree): Int = t match {
    case Leaf          => 0
    case Node(_, l, r) => 1 + math.max(depth(l), depth(r))
  }
  def main(args: Array[String]): Unit = {
    println(depth(Node(1, Leaf, Node(2, Leaf, Leaf))))
  }
}

Perché è importante

L'esaustività verificata dal compilatore offre:

  • La certezza che ogni caso venga gestito
  • Promemoria automatici quando l'ADT cresce
  • Meno MatchError a runtime
  • Un refactoring su larga scala più sicuro

Mettere insieme i concetti

Un ADT sealed con copertura completa. Aggiungere una nuova variante attiverebbe qui un avviso del compilatore.

sealed trait Command
case object Start extends Command
case object Stop extends Command
case class SetSpeed(v: Int) extends Command
object Main {
  def run(c: Command): String = c match {
    case Start       => "starting"
    case Stop        => "stopping"
    case SetSpeed(v) => s"speed $v"
  }
  def main(args: Array[String]): Unit = {
    List(Start, SetSpeed(5), Stop).foreach(c => println(run(c)))
  }
}

Verifica rapida

Verifichi la Sua comprensione del matching esaustivo.

Riepilogo

Ha imparato a conoscere il matching esaustivo:

  • Un match è esaustivo quando copre ogni variante
  • Per i trait sealed il compilatore lo verifica e segnala le lacune
  • L'aggiunta di una variante fa emergere ogni match incompleto
  • Eviti case _ con gli ADT sealed per mantenere questa protezione
  • Le guardie possono compromettere l'esaustività; aggiunga un fallback senza guardia

Domande Frequenti

La lezione «Corrispondenza esaustiva» è gratuita?

Sì — il testo completo di «Corrispondenza esaustiva» è 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 «Corrispondenza esaustiva»?

Completezza verificata dal compilatore 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 «Corrispondenza esaustiva»?

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. Case class
  2. Trait sealed
  3. Tipi di dati algebrici
  4. Corrispondenza esaustiva
← Torna a Scala for Backend Engineering & Functional Programming