Implizite Materialisierung im selben Modul
Ich habe eine parametrisierte Klasse wie
class Test[T]{
//...
}
object Test{
implicit def materializeTest[T]: Test[T] = macro impl[T]
def impl[T: c.WeakTypeTag](c: blackbox.Context) = //...
}
Wenn Sie das materialisierte Implizit aus demselben Modul verwenden, wird ein Fehler ausgegeben:
macro implementation not found
Das Problem ist jedoch, dass das Extrahieren einer einzelnen Klasse in ein separates Modul absolut hässlich und umständlich aussieht. Vielleicht gibt es eine "bekannte Problemumgehung", um dies zu vermeiden? Vielleicht kann hier formlos hilfreich sein?
UPD:
scalaVersion in ThisBuild := "2.13.2"
Hier ist mein minimales Beispiel:
import scala.language.experimental.macros
import scala.reflect.macros.blackbox
object Main {
sealed trait Adt
case object Adt1 extends Adt
case object Adt2 extends Adt
trait Test[Adtt <: Adt] {
def restrict(restrictions: List[Int]): List[Int]
}
object Test {
def apply[Adtt <: Adt](implicit ev: Test[Adtt]): Test[Adtt] = ev
implicit def implicitMaterializer[
Adtt <: Adt
]: Test[Adtt] = macro impl[Adtt]
def impl[Adtt <: Adt: c.WeakTypeTag](
c: blackbox.Context
): c.Expr[Test[Adtt]] = {
import c.universe._
c.Expr[Test[Adtt]](q"""???""")
}
}
def main(args: Array[String]): Unit = {
Test[Adt1.type].restrict(List(1, 2, 3))
}
}
was zu folgendem Fehler führt:
[error] Main.scala:32:9: macro implementation not found: implicitMaterializer
[error] (the most common reason for that is that you cannot use macro implementations in the same compilation run that defines them)
Antworten
Sie können Test
aber nicht in ein separates Modul extrahierenTestMacro
Ader
import scala.language.experimental.macros
class Test[T]
object Test {
implicit def materializeTest[T]: Test[T] = macro TestMacro.impl[T]
}
implicitly[Test[Int]] // compiles
Makros
import scala.reflect.macros.blackbox
object TestMacro {
def impl[T: c.WeakTypeTag](c: blackbox.Context) = {
import c.universe._
q"new Test[${weakTypeOf[T]}]"
}
}
Hässlich oder nicht, aber Makroimplementierungen müssen kompiliert werden, bevor sie angewendet werden.
Dies wird in Scala 3 verbessert
http://dotty.epfl.ch/docs/reference/metaprogramming/macros.html#defining-a-macro-and-using-it-in-a-single-project
Shapeless verbirgt nur einige vordefinierte Standardmakros. Es kann nicht mit Ihren eigenen Makros helfen.