Aynı modülde örtük materyalizasyon

Dec 15 2020

Gibi parametreli bir sınıfım var

class Test[T]{
    //...
}

object Test{
    implicit def materializeTest[T]: Test[T] = macro impl[T]

    def impl[T: c.WeakTypeTag](c: blackbox.Context) = //...
}

Aynı modülden materyalize edilmiş örtük kullanılırsa, bir hata atar:

macro implementation not found

Ancak sorun, tek bir sınıfı ayrı bir modüle çıkarmak, kesinlikle çirkin ve hantal görünüyor. Belki bundan kaçınmak için "iyi bilinen bir çözüm" vardır? Belki şekilsiz burada yardımcı olabilir?

UPD:

scalaVersion in ThisBuild := "2.13.2"

İşte minimal örneğim:

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))
  }
}

bu aşağıdaki hataya neden olur:

[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)

Yanıtlar

3 DmytroMitin Dec 15 2020 at 21:35

Ayrı bir modüle çıkartabilirsiniz TestancakTestMacro

çekirdek

import scala.language.experimental.macros

class Test[T]

object Test {
  implicit def materializeTest[T]: Test[T] = macro TestMacro.impl[T]
}

implicitly[Test[Int]] // compiles

makrolar

import scala.reflect.macros.blackbox

object TestMacro {
  def impl[T: c.WeakTypeTag](c: blackbox.Context) = {
    import c.universe._
    q"new Test[${weakTypeOf[T]}]"
  }
}

Çirkin ya da değil ama makro uygulamalar uygulanmadan önce derlenmelidir.

Bu, Scala 3'te geliştirildi

http://dotty.epfl.ch/docs/reference/metaprogramming/macros.html#defining-a-macro-and-using-it-in-a-single-project

Shapeless, önceden tanımlanmış bazı standart makroları gizler, kendi makrolarınızda yardımcı olamaz.