我有一个成员类型的特征,并且想要一个带有包含此类型的签名的宏:
trait Foo {
class Bar[A] { ... }
def baz[A](x: Bar[A]): Bar[A] = macro bazImpl[A]
def bazImpl[A: c.WeakTypeTag](c: blackbox.Context)(x: c.Expr[Bar[A]]) = ...
}
这不起作用,因为 bazImpl
必须属于静态(即非成员)对象
或宏包。但在这两种情况下,我都没有 foo: Foo
,因此我可以编写 foo.Bar[A]
。
我能想到的一个解决方法是使用 Foo#Bar[A]
并添加强制转换:
trait Foo {
class Bar[A] { ... }
def baz[A](x: Bar[A]): Bar[A] = Foo.baz1(x).asInstanceOf[Bar[A]]
def bazImpl[A: c.WeakTypeTag](c: blackbox.Context)(x: c.Expr[Bar[A]]) = ...
}
object Foo {
def baz1[A](x: Foo#Bar[A]): Foo#Bar[A] = macro bazImpl[A]
def bazImpl[A: c.WeakTypeTag](c: blackbox.Context)(x: c.Expr[Foo#Bar[A]]): c.Expr[Foo#Bar[A]] = ...
}
但我想避免它(既因为它不完全是类型安全的,又因为实际情况更复杂)。还有其他选择吗?
最佳答案
如果您使用的是 Scala 2.11,只需在各处编写 c.Tree
而不是 c.Expr
。这将减少在宏实现中指定与宏定义中完全相同的类型的样板,成本几乎为零。与 exprs 相比,树的唯一潜在缺点是 reify,它要求拼接是 exprs,但由于现在 Scala 中的大多数元程序都是用准引号编写的,因此这对您来说可能并不重要。
关于引用成员类型的 Scala 宏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30538226/