0

我使用了来自Macro Paradise的 Eugene Burmako 的宏注释示例(感谢 Eugene!),并在此处对其进行了修改以将 a 添加到此处val的空类中。

例如,我可以val按预期调用 new 。但是当我尝试使用更新的类作为类型参数时,例如在Salat(解析 Scala sig)或Scalavro(使用 2.10 反射)中,该类看起来仍然是空的(即好像val从未添加过)。

由于 Salat 解析了 Scala 签名,我检查了一下,它比普通签名短了大约 30 个条目,并且条目的顺序不同。然而,签名似乎确实包含有关添加的val.

那么为什么新的 val 信息无法访问,有什么办法可以做到吗?谢谢参观。

4

1 回答 1

1

只是将 val 添加到模板中不会自动使其成为构造函数参数。为此,构造函数本身也需要进行调整。幸运的是,我们有 quasiquotes,与手动构建树相比,它大大简化了这项任务。

case q"$mods class $name[..$tparams](..$first)(...$rest) extends ..$parents { $self => ..$body }" :: Nil =>
  val CASEACCESSOR = (1 << 24).toLong.asInstanceOf[FlagSet]
  val PARAMACCESSOR = (1 << 29).toLong.asInstanceOf[FlagSet]
  val helloMods = Modifiers(CASEACCESSOR | PARAMACCESSOR | DEFAULTPARAM)
  val helloVal = q"""$helloMods val x: String = "hello macro!""""
  q"$mods class $name[..$tparams](..$first, $helloVal)(...$rest) extends ..$parents { $self => ..$body }"

注意几个怪癖:1)我们需要设置官方 API 中不存在的 CASEACCESSOR 和 PARAMACCESSOR 标志以避免在 Salat 中崩溃,2)我们需要设置 DEFAULTPARAM 以确保 scalac 识别我们的默认值参数作为默认值,3)默认参数不能推断出它们的类型,所以我们需要在这里显式地提供String。

于 2013-11-01T02:44:12.710 回答