0

我一直在研究复杂的编译时反射,并且遇到了使用 AST 手动制作 Scala 代码的需求。在进行实验时,我注意到一个奇怪的编译错误,这对我来说并没有什么意义,所以我尝试在一个测试项目中重现它。

我使用Scala 2.10.4

这是代码:

宏.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
}

测试者.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())

我得到的编译错误是value now is not a member of java.time.OffsetDateTime在调用Macro.manualAstTest.
正如回声的输出所暗示的那样,这两个表达式是相同的——但一个有效(来自 的表达式reify)而另一个无效(使用 apply-select 制作的表达式)。

两者之间可能有什么区别?

4

1 回答 1

0

设法找到了罪魁祸首。
显然typeOf[OffsetDateTime].typeSymbol返回符号,就像从 Scala 类返回的一样,即没有它的静态成员。

添加.companionSymbol似乎会像从 Scala 对象返回的那样返回符号,也就是说,只有静态成员(顾名思义......)

因此,以下更改使其起作用:

val odtSymbol = typeOf[OffsetDateTime].typeSymbol.companionSymbol
于 2017-03-15T22:37:03.010 回答