0Pricing
Scala for Backend Engineering & Functional Programming · Lezione

Macro pratiche

Casi d'uso

Macro pratiche è 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.

Le macro nel mondo reale

Oltre gli esempi didattici, le macro risolvono problemi concreti: catturare il contesto del codice sorgente, derivare type class, validare valori letterali e generare codice senza boilerplate.

Caso d'uso: assert con messaggio

Una macro può catturare il testo sorgente di una condizione fallita per produrre automaticamente un messaggio utile per l'asserzione.

import scala.quoted.*

inline def myAssert(inline cond: Boolean): Unit =
  ${ assertImpl('cond) }

Catturare il codice sorgente

All'interno della macro, cond.show (tramite l'API reflect) restituisce il codice sorgente letterale dell'espressione, che può essere inserito nel messaggio di errore.

import scala.quoted.*

def assertImpl(cond: Expr[Boolean])(using q: Quotes): Expr[Unit] = {
  import q.reflect.*
  val src = Expr(cond.asTerm.show)
  '{ if (!${ cond }) throw new AssertionError("failed: " + ${ src }) }
}

Caso d'uso: validazione in fase di compilazione

Validi un valore letterale, ad esempio una regex o un numero di porta, in fase di compilazione, così i valori non validi non arrivano mai a runtime.

import scala.quoted.*

inline def port(inline n: Int): Int = ${ portImpl('n) }

Interrompere l'elaborazione per input non valido

Estragga il valore letterale, lo verifichi e chiami report.errorAndAbort per i valori non validi, trasformando un bug a runtime in un errore di compilazione.

import scala.quoted.*

def portImpl(n: Expr[Int])(using q: Quotes): Expr[Int] = {
  import q.reflect.*
  val v = n.valueOrAbort
  if (v < 1 || v > 65535) report.errorAndAbort("invalid port")
  n
}

Caso d'uso: derivazione di type class

Le macro, spesso tramite inline + scala.deriving.Mirror, possono generare istanze di type class, come encoder JSON, per qualsiasi case class senza boilerplate.

import scala.deriving.Mirror

trait Show[T] { def show(t: T): String }

inline def derived[T](using Mirror.Of[T]): Show[T] = ???

Usare Mirror

Un Mirror espone in fase di compilazione i tipi e le etichette dei campi di un product. In combinazione con inline, consente di iterare sui campi per costruire un'istanza.

import scala.deriving.*
import scala.compiletime.*

inline def labels[T](using m: Mirror.ProductOf[T]): List[String] =
  constValueTuple[m.MirroredElemLabels].toList.map(_.toString)

Caso d'uso: logging con posizione

Una macro può leggere Position dall'API reflect per associare ai messaggi di log il file e il numero di riga, senza costi a runtime.

import scala.quoted.*

def posImpl(using q: Quotes): Expr[String] = {
  import q.reflect.*
  val p = Position.ofMacroExpansion
  Expr(s"${p.sourceFile.name}:${p.startLine + 1}")
}

Quando NON usare le macro

Le macro sono potenti, ma costose da mantenere e sottoporre a debug. Preferisca prima funzioni normali, metodi inline o derivazione con given. Ricorra alle macro solo quando queste soluzioni non sono sufficienti.

Testare le macro

Testi il comportamento generato come farebbe con il codice ordinario e verifichi che gli input non validi non vengano compilati, usando strumenti come typeCheckErrors delle utilità di test in fase di compilazione.

Analogo a runtime

Una macro di validazione in fase di compilazione produce lo stesso effetto di questo controllo autonomo a runtime, ma l'errore si verifica durante la compilazione anziché a runtime.

object Main {
  def port(n: Int): Int = {
    require(n >= 1 && n <= 65535, "invalid port")
    n
  }
  def main(args: Array[String]): Unit = {
    println(port(8080)) // 8080
  }
}

Verifica rapida

Qual è il principale vantaggio di validare un valore letterale con una macro invece che a runtime?

Riepilogo

Ha esplorato alcuni casi d'uso pratici delle macro:

  • assert con cattura del codice sorgente
  • validazione in fase di compilazione con errorAndAbort
  • derivazione di type class tramite Mirror
  • logging con informazioni sulla posizione
  • quando evitare le macro e come sottoporle a test

Ha completato il corso di metaprogrammazione e macro.

Domande Frequenti

La lezione «Macro pratiche» è gratuita?

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

Casi d'uso 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 «Macro pratiche»?

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. Metodi inline
  2. Basi delle macro
  3. Quote e splice
  4. Macro pratiche
← Torna a Scala for Backend Engineering & Functional Programming