同じモジュールでの暗黙の具体化
Dec 15 2020
私は次のようなパラメータ化されたクラスを持っています
class Test[T]{
//...
}
object Test{
implicit def materializeTest[T]: Test[T] = macro impl[T]
def impl[T: c.WeakTypeTag](c: blackbox.Context) = //...
}
同じモジュールからマテリアライズされた暗黙を使用すると、エラーがスローされます。
macro implementation not found
しかし、問題は、単一のクラスを別のモジュールに抽出することは、絶対に醜くて面倒に見えることです。多分それを避けるためにいくつかの「よく知られた回避策」がありますか?たぶん形のないものがここで役立つことがありますか?
UPD:
scalaVersion in ThisBuild := "2.13.2"
これが私の最小限の例です:
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))
}
}
その結果、次のエラーが発生します。
[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)
回答
3 DmytroMitin Dec 15 2020 at 21:35
別のモジュールに抽出することはできますTest
が、TestMacro
芯
import scala.language.experimental.macros
class Test[T]
object Test {
implicit def materializeTest[T]: Test[T] = macro TestMacro.impl[T]
}
implicitly[Test[Int]] // compiles
マクロ
import scala.reflect.macros.blackbox
object TestMacro {
def impl[T: c.WeakTypeTag](c: blackbox.Context) = {
import c.universe._
q"new Test[${weakTypeOf[T]}]"
}
}
醜いかどうかはわかりませんが、マクロの実装は、適用する前にコンパイルする必要があります。
これはScala3で改善されています
http://dotty.epfl.ch/docs/reference/metaprogramming/macros.html#defining-a-macro-and-using-it-in-a-single-project
Shapelessは、事前定義された標準マクロのセットを非表示にするだけで、独自のマクロには役立ちません。