jed*_*sah 5 types scala metaprogramming scala-macros
我有以下宏:
def testMacro[T](x: T): Option[T] = macro testMacroImpl[T]
def testMacroImpl[T: c.WeakTypeTag](c: Context)(x: c.Expr[T]): c.Expr[Option[T]] = {
import c.universe._
val newTree = x.tree match {
case Block(List(first), second) => {
val newFirst = first match {
case ValDef(mods, name, _, rhs) => ValDef(mods, name, EmptyTree, q"Some($rhs)")
}
Block(List(newFirst), second)
}
}
c.Expr[Option[T]](newTree)
}
Run Code Online (Sandbox Code Playgroud)
基本上,这应该改变这个:
testMacro {
val aa = "hello"
aa
}
Run Code Online (Sandbox Code Playgroud)
成
{
val aa = Some("hello")
aa
}
Run Code Online (Sandbox Code Playgroud)
但是,它失败并出现以下错误:
[error] found : String
[error] required: Option[String]
[error] val f = IdiomBracket.testMacro{
[error]
^
Run Code Online (Sandbox Code Playgroud)
我的调查显示这是因为它接收到标识符aa具有类型的类型化树String.由于代码转换,它现在是类型,Option[String]但标识符的类型尚未更新.我尝试创建一个新的(无类型)标识符,这只会产生错误:
[error] found : <notype>
[error] required: Option[String]
[error] val f = IdiomBracket.testMacro{
[error] ^
Run Code Online (Sandbox Code Playgroud)
我已经尝试在发送之前对树进行类型检查,希望这样可以填写正确的类型,但这似乎没有任何效果.
作为参考,这里是创建一个新的Ident并执行类型检查的相同的宏,但遗憾的是它仍然不起作用.
def testMacroImpl[T: c.WeakTypeTag](c: Context)(x: c.Expr[T]): c.Expr[Option[T]] = {
import c.universe._
val newTree = x.tree match {
case Block(List(first), second) => {
val newFirst = first match {
case ValDef(mods, name, _, rhs) => ValDef(mods, name, EmptyTree, q"Some($rhs)")
}
val newSecond = second match {
case ident: Ident => Ident(ident.name)
}
Block(List(newFirst), newSecond)
}
}
c.Expr[Option[T]](c.typecheck(newTree))
}
Run Code Online (Sandbox Code Playgroud)
这行:
case ValDef(mods, name, _, rhs) => ValDef(mods, name, EmptyTree, q"Some($rhs)")
Run Code Online (Sandbox Code Playgroud)
需要更改为这一行:
case ValDef(mods, name, _, rhs) => ValDef(mods, name, TypeTree(), q"Some($rhs)")
Run Code Online (Sandbox Code Playgroud)
将 EmptyTree 作为 ValDef 中的类型可能永远没有意义。可惜编译器不能告诉我这一点,这样我就可以节省 48 小时的兼职工作。
| 归档时间: |
|
| 查看次数: |
162 次 |
| 最近记录: |