私は複雑なコンパイル時のリフレクションに取り組んでおり、ASTを使用して手動でScalaコードを作成する必要があります。私は実際に私には意味をなさない奇妙なコンパイルエラーに気づいたので、テストプロジェクトでそれを再現することを試みました。コードがReefなしで作成されたときにScalaマクロがコンパイルされない
Scala 2.10.4を使用します。
ここでは、コードです:
Macro.scala:
object Macro {
def reifyTestImpl(c: Context): c.Expr[OffsetDateTime] = {
import c.universe._
val expression = reify(OffsetDateTime.now())
c.echo(c.enclosingPosition, "With reify: " + show(expression.tree))
c.echo(c.enclosingPosition, "With reify (raw): " + showRaw(expression.tree))
expression
}
def manualAstTestImpl(c: Context): c.Expr[OffsetDateTime] = {
import c.universe._
val odtSymbol = typeOf[OffsetDateTime].typeSymbol
val now = newTermName("now")
val expression = c.Expr(
Apply(
Select(Ident(odtSymbol), now),
List()
)
)
c.echo(c.enclosingPosition, "Manual: " + show(expression.tree))
c.echo(c.enclosingPosition, "Manual (raw): " + showRaw(expression.tree))
expression
}
def reifyTest = macro reifyTestImpl
def manualAstTest = macro manualAstTestImpl
}
Tester.scala:
object Tester {
def main(args: Array[String]): Unit = {
println(Macro.reifyTest)
println(Macro.manualAstTest)
}
}
c.echo
からの出力は次のとおりです。
With reify: OffsetDateTime.now()
With reify (raw): Apply(Select(Ident(java.time.OffsetDateTime), newTermName("now")), List())
Manual: OffsetDateTime.now()
Manual (raw): Apply(Select(Ident(java.time.OffsetDateTime), newTermName("now")), List())
コンパイルが私はMacro.manualAstTest
への呼び出しでvalue now is not a member of java.time.OffsetDateTime
を取得するエラーが発生します。
エコーからの出力が示唆するように、2つの式は同じですが、一方は動作し(reify
の式)、もう一方は動作しません(apply-selectで作成された式)。
2つの違いは何ですか?