2013-10-31 41 views
0

我使用了来自Macro Paradise(感谢Eugene!)的Eugene Burmako的宏注释示例,并在此修改它以将val添加到空类hereScala宏注释 - 为什么当我将它用作类型参数时,我的类不会更新?

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

由于Salat解析了Scala签名,我检查了它,并且它比正常签名要短约30个条目,并且条目的顺序也不相同。然而它确实看起来签名包括有关添加的val的信息。

那么为什么新的val信息不可访问,并且有什么方法可以使它成为如此吗?谢谢参观。

回答

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)我们需要设置CASEACCESSOR和PARAMACCESSOR标志不存在官方的API中为了避免撞车萨拉特,2),我们需要以设定DEFAULTPARAM到确保scalac将默认参数识别为默认参数,3)默认参数不能推断它们的类型,所以我们需要在这里显式地提供String。

+0

太棒了!我需要quasiquotes的例子,谢谢一堆(同时,好的错误信息正在帮助我)。我已更新我的项目以显示工作示例。 –

+0

随着最新的quasiquotes,你不需要任何caseaccessor | paramacessor魔法,这些标志将自动设置在幕后。 –

+1

p.s.实际上DEFAULTPARAM也不是必需的。只需创建一个val并将其拼接到参数位置,它应该可以正常工作。 –

相关问题