Scala宏指的是成员类型

时间:2015-05-29 20:09:21

标签: scala scala-macros scala-2.11 scala-reflect

我有一个具有成员类型的特征,并希望拥有一个包含此类型的签名的宏:

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]] = ... 
}

但是我想避免它(因为它不是完全类型安全的,因为真实情况更复杂)。任何替代方案?

1 个答案:

答案 0 :(得分:2)

如果您正在使用Scala 2.11,请在任何地方写c.Tree而不是c.Expr。这将削减指定宏观投影中非常相同类型的样板,就像在宏定义中一样,几乎为零成本。与exprs相比,树的唯一潜在缺点是reify,这需要拼接为exprs,但由于现在Scala中的大多数元程序都是用quasiquotes编写的,所以很可能这对你来说不重要。