引用成员类型的 Scala 宏

标签 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 必须属于静态(即非成员)对象 或宏包。但在这两种情况下,我都没有 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/

相关文章:

scala - 如何在 akka 中使用 "ask"作为三个值

java - Maven:在一个项目中混合使用 Java 和 Scala

scala - 使用 Scala 的宏来强制类型相等

scala - 如何在设置属性值之前和之后存储对象状态

Scala 宏 : Create new classes with Option types

Java 与 Scala 线程——在 JVM 的幕后

Scala 转换长到日期时间

Scala 类型约束来检查参数值

scala - 如何键入检查 Def Def

scala - 如何在 scala 枚举值中添加点