How can parameters/settings be passed to a Scala macro?

╄→гoц情女王★ 提交于 2019-12-05 01:52:39

The parameter lists of your method and the macro definition have to line up exactly, with the macro definition method having an extra initial parameter list for the context, and every other parameter from the method definition having the same name and the same type wrapped in a c.Expr. (Note however that the type parameter lists can differ.)

This means that you can't pass information to the macro implementation as arguments in your method definition. You can use a static annotation to accomplish the same thing, though (this is a trick I learned from Eugene Burmako, who used it to implement structural types without reflective access, a.k.a. vampire methods):

import scala.annotation.StaticAnnotation
import scala.language.experimental.macros
import scala.reflect.macros.whitebox.Context

class setting(value: String) extends StaticAnnotation

def internalMacro(c: Context)(param: c.Expr[Int]) = {
  import c.universe._
  val settingValue = c.macroApplication.symbol.annotations.filter(
    _.tree.tpe <:< typeOf[setting]
  ).headOption.flatMap(
    _.tree.children.tail.collectFirst {
      case Literal(Constant(s: String)) => s
    }
  ).getOrElse(
    c.abort(c.enclosingPosition, "Annotation body not provided!")
  )
  settingValue match {
    case "setting 1" => c.Expr(q"42")
    case _ => param
  }
}

And then:

scala> @setting("setting 1") def a(param: Int): Int = macro internalMacro
defined term macro a: (param: Int)Int

scala> @setting("setting 2") def b(param: Int): Int = macro internalMacro
defined term macro b: (param: Int)Int

scala> def c(param: Int): Int = macro internalMacro
defined term macro c: (param: Int)Int

scala> a(10)
res0: Int = 42

scala> b(10)
res1: Int = 10

scala> c(10)
<console>:22: error: Annotation body not provided!
              c(10)
               ^

And I didn't even examine any enclosing trees. See my blog post here for an example of this approach in action.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!