0
我一直在进行复杂的编译时反射,并且遇到了需要使用AST手动编写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
。
由于回声的输出表明,这两个表达式是相同的 - 但一个作品(表达从reify
),另一个没有(用apply-select制作的表达)。
这两者有什么区别?