Macro implicita. Valore implicito predefinito. Come?
Non so nemmeno come fare la domanda.
Ho una macro che crea un'istanza di IsEnum[T]per un tipo T.
Sto effettuando dei test e voglio assicurarmi che l'implicito non venga trovato per i tipi che non sono chiusi o che, in generale, non soddisfano i requisiti di un'enumerazione.
Quindi ho creato questo metodo per i test
def enumOf[T](implicit isEnum:IsEnum[T] = null) = isEnum
E poi lo assicuro enumOf[NotAnEnum] == null
Ma invece, fallisce in fase di compilazione.
Una cosa è l'errore macro. Un'altra cosa è che la macro non si applica per un determinato caso. Come fare questa distinzione durante la creazione di macro?
Modifica: ho usato c.aborte c.error, entrambi mi hanno dato gli stessi risultati.
Risposte
Sembra che tu non abbia creato la tua IsEnumwhitebox di tipo macro materializzante . Normalmente le macro implicite dovrebbero essere whitebox.
import scala.language.experimental.macros
import scala.reflect.macros.whitebox
trait IsEnum[T]
object IsEnum {
implicit def mkIsEnum[T]: IsEnum[T] = macro mkIsEnumImpl[T]
def mkIsEnumImpl[T: c.WeakTypeTag](c: whitebox.Context): c.Tree = {
import c.universe._
val typ = weakTypeOf[T]
val classSymbol = typ.typeSymbol.asClass
if (!classSymbol.isTrait || !classSymbol.isSealed) c.abort(c.enclosingPosition, s"$typ must be sealed trait") val symbols = classSymbol.knownDirectSubclasses symbols.collectFirst { case symbol if !symbol.isModuleClass || !symbol.asClass.isCaseClass => c.abort(c.enclosingPosition, s"${symbol.asClass.toType} must be case object")
}
q"new IsEnum[$typ] {}"
}
}
def enumOf[T](implicit isEnum: IsEnum[T] = null) = isEnum
Utilizzo:
sealed trait A
object A {
case object B extends A
case object C extends A
case class D() extends A
}
enumOf[A] //null
sealed trait A
object A {
case object B extends A
case object C extends A
class D extends A
}
enumOf[A] //null
sealed trait A
object A {
case object B extends A
object C extends A
}
enumOf[A] //null
trait A
object A {
case object B extends A
case object C extends A
}
enumOf[A] //null
sealed trait A
object A {
case object B extends A
case object C extends A
}
enumOf[A] //App$$anon$1@47f37ef1
Il runtime delle macro è il tempo di compilazione del codice principale. Se una macro blackbox (anche una macro blackbox implicita) genera un'eccezione, sarà un errore di compilazione durante la compilazione del codice principale. Se una macro implicita di whitebox genera un'eccezione, durante la compilazione del codice principale l'implicito verrà rimosso silenziosamente dai candidati.
https://docs.scala-lang.org/overviews/macros/blackbox-whitebox.html