Materialisasi implisit dalam modul yang sama
Saya memiliki kelas berparameter seperti
class Test[T]{
//...
}
object Test{
implicit def materializeTest[T]: Test[T] = macro impl[T]
def impl[T: c.WeakTypeTag](c: blackbox.Context) = //...
}
Jika menggunakan materialized implisit dari modul yang sama, kesalahan ini muncul:
macro implementation not found
Tetapi masalahnya adalah mengekstrak satu kelas menjadi modul terpisah terlihat sangat jelek dan tidak praktis. Mungkin ada beberapa "solusi terkenal" untuk menghindarinya? Mungkin tak berbentuk bisa membantu di sini?
UPD:
scalaVersion in ThisBuild := "2.13.2"
Inilah contoh minimal saya:
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))
}
}
yang menghasilkan kesalahan berikut:
[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)
Jawaban
Anda tidak dapat mengekstrak ke modul terpisah Test
tetapiTestMacro
inti
import scala.language.experimental.macros
class Test[T]
object Test {
implicit def materializeTest[T]: Test[T] = macro TestMacro.impl[T]
}
implicitly[Test[Int]] // compiles
makro
import scala.reflect.macros.blackbox
object TestMacro {
def impl[T: c.WeakTypeTag](c: blackbox.Context) = {
import c.universe._
q"new Test[${weakTypeOf[T]}]"
}
}
Jelek atau tidak, tetapi implementasi makro harus dikompilasi sebelum diterapkan.
Ini ditingkatkan di Scala 3
http://dotty.epfl.ch/docs/reference/metaprogramming/macros.html#defining-a-macro-and-using-it-in-a-single-project
Shapeless hanya menyembunyikan beberapa kumpulan makro standar yang telah ditentukan sebelumnya, itu tidak dapat membantu dengan makro Anda sendiri.