एक ही मॉड्यूल में निहित भौतिककरण

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]}]"
  }
}

लागू होने से पहले बदसूरत या नहीं, लेकिन मैक्रो कार्यान्वयन को संकलित किया जाना चाहिए।

यह स्कैला 3 में सुधार हुआ है

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

शेपलेस बस मानक मैक्रोज़ के कुछ पूर्वनिर्धारित सेट को छुपाता है, यह आपके अपने मैक्रोज़ के साथ मदद नहीं कर सकता है।