3

マクロからマクロを呼び出そうとしていますが、何か間違っています。おおよそ次のようになります。

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

    ???
  }
}

つまり、 のタイプの何らかの条件に基づいてA、マクロでツリーを生成する代わりに、別のマクロ ( ) の本体を返したいと考えていJson.formatます。しかし、どういうわけか、これはマクロを使用する前にすでに展開されています。これをコンパイルすると、

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

これは、formatすでに実行されていることを意味します (実行されるべきではありません)。メソッドは次のformatように定義されます。

def format[A] = macro JsMacroImpl.formatImpl[A]
4

2 に答える 2

2

あるいは、両方のマクロを異なるコンパイル単位 (つまり、異なるプロジェクト) に配置すると、マクロからマクロを呼び出すことができるはずです。Scala は、マクロをコンパイルして、同じコンパイル実行で適用することはできません。

于 2013-06-18T10:46:06.450 に答える
2

次のように見えるマクロ本体に直接ジャンプする必要があります。

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

(IntelliJにはこの赤があったので違うと思っていたのですが、実際にコンパイルされます)

于 2013-06-18T09:11:28.387 に答える