Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calling a macro from a macro

Tags:

macros

scala

I am trying to call a macro from a macro, but I'm doing something wrong. It looks approximately like this:

import play.api.libs.json._
import scala.reflect.macros.Context
import language.experimental.macros

object Extension {

  def apply[A]: Format[A] = macro applyImpl[A]

  def applyImpl[A: c.WeakTypeTag](c: Context): c.Expr[Format[A]] = {
    import c.universe._
    val aTpeW   = c.weakTypeOf[A]
    val aClazz  = aTpeW.typeSymbol.asClass

    if (!aClazz.isSealed) { // fall back to Json.format
      val t = reify { Json.format[A] } .tree
      return c.Expr[Format[A]](t)
    }

    ???
  }
}

In other words, based on some condition of the type of A, instead of generating a tree in my macro, I want to return the body of another macro (Json.format). But somehow this gets expanded already before using the macro. When I compile this, I get

[error] .../Extension.scala:47: No unapply function found
[error]       val t = reify { Json.format[A] } .tree
[error]                                  ^

Which means that format is already executed (it should not be). The format method is defined as

def format[A] = macro JsMacroImpl.formatImpl[A]
like image 331
0__ Avatar asked Feb 04 '26 18:02

0__


2 Answers

One needs to jump right into the macro body it seems:

if (!aClazz.isSealed) { // fall back to Json.format
  return JsMacroImpl.formatImpl[A](c)
}

(IntelliJ had this red, so I thought it was wrong, but it actually compiles)

like image 119
0__ Avatar answered Feb 07 '26 18:02

0__


Alternatively you should be able to call the macro from a macro, when you put both macros in different compilation units (i.e. different projects). Scala cannot compile a macro and apply it in the same compilation run.

like image 36
stefan.schwetschke Avatar answered Feb 07 '26 18:02

stefan.schwetschke



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!