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製作的表達)。
這兩者有什麼區別?