2

我有一个成员类型的特征,并且想要一个带有包含此类型的签名的宏:

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必须属于静态(即非成员)object或宏包。但在这两种情况下,我都没有一个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]] = ... 
}

但我想避免它(既因为它不完全是类型安全的,又因为实际情况更复杂)。有什么选择吗?

4

1 回答 1

2

如果您使用的是 Scala 2.11,只需c.Tree在任何地方编写而不是c.Expr. 这将减少在宏 impls 中指定与在宏 defs 中相同类型的样板,几乎为零成本。与 exprs 相比,树的唯一潜在缺点是 reify,它要求拼接对象是 exprs,但由于现在 Scala 中的大多数元程序都是用准引号编写的,所以这对你来说可能无关紧要。

于 2015-05-29T22:27:18.270 回答