在两个宏之间进行通信

时间:2015-05-09 19:03:10

标签: scala scala-macros

是否可以通过宏foo验证宏bar被调用了两次?

更多细节:

trait Foo {
    foo() 
}

class Bar extends Foo {
    bar()
    bar()
}

我希望只有在bar()被调用两次时才能编译。

1 个答案:

答案 0 :(得分:1)

Sure-macros可以像任何其他Scala代码一样维护可变状态:

import scala.language.experimental.macros
import scala.reflect.macros.Context

object Macros {
  var counter = 0

  def foo_impl(c: Context)(): c.Expr[Unit] = {
    import c.universe._
    if (counter == 2) c.Expr[Unit](q"()") else c.abort(
      c.enclosingPosition,
      "Didn't call bar twice!"
    )
  }

  def bar_impl(c: Context)(): c.Expr[Unit] = {
    import c.universe._
    counter += 1
    c.Expr[Unit](q"()")
  }
}

然后:

scala> def bar() = macro Macros.bar_impl
defined term macro bar: ()Unit

scala> def foo() = macro Macros.foo_impl
defined term macro foo: ()Unit

scala> foo()
<console>:14: error: Didn't call bar twice!
              foo()
                 ^

scala> bar()

scala> foo()
<console>:14: error: Didn't call bar twice!
              foo()
                 ^

scala> bar()

scala> foo()

这似乎是一个非常糟糕的主意,但如果你真的想这样做,你就可以做到。