Makro implisit. Nilai implisit default. Bagaimana?
Saya bahkan tidak tahu bagaimana mengajukan pertanyaan itu.
Saya memiliki makro yang membuat instance IsEnum[T]untuk suatu tipe T.
Saya melakukan pengujian untuk itu, dan ingin memastikan bahwa implisit tidak ditemukan untuk tipe yang tidak disegel, atau yang, secara umum, tidak memenuhi persyaratan enum.
Jadi saya membuat metode ini untuk pengujian
def enumOf[T](implicit isEnum:IsEnum[T] = null) = isEnum
Dan kemudian saya memastikan itu enumOf[NotAnEnum] == null
Namun sebaliknya, gagal pada waktu kompilasi.
Satu hal adalah kesalahan makro. Hal lain adalah makro tidak berlaku untuk kasus tertentu. Bagaimana cara membuat perbedaan itu saat membuat makro?
Sunting: Saya telah menggunakan c.abortdan c.error, keduanya memberi saya hasil yang sama.
Jawaban
Kedengarannya seperti Anda tidak membuat kotak IsEnumputih kelas jenis terwujud makro Anda . Biasanya makro implisit harus kotak putih.
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
Pemakaian:
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
Waktu kerja makro adalah waktu kompilasi kode utama. Jika makro kotak hitam (bahkan makro kotak hitam implisit) melontarkan pengecualian, maka itu akan menjadi kesalahan kompilasi selama kompilasi kode utama. Jika makro implisit kotak putih melontarkan pengecualian maka selama kompilasi kode utama, implisit akan dihapus secara diam-diam dari kandidat.
https://docs.scala-lang.org/overviews/macros/blackbox-whitebox.html