繁体   English   中英

如何将参数/设置传递给Scala宏?

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

如何将参数/设置传递给Scala宏?

这些设置不应该是全局的,而是每次宏调用。

我想要的是类似的东西:

def a(param: Int) = macro internalMacro("setting 1")
def b(param: Int) = macro internalMacro("setting 2")

然而, setting 1setting 2应该是常量值,可以从宏内访问,因此我可以使内部行为依赖于它们。

您的方法和宏定义的参数列表必须准确排列,宏定义方法具有上下文的额外初始参数列表,并且方法定义中的每个其他参数具有相同的名称和相同的类型包含在c.Expr (但请注意,类型参数列表可能不同。)

这意味着您无法将信息作为方法定义中的参数传递给宏实现。 你可以使用静态注释来完成同样的事情(这是我从Eugene Burmako那里学到的一个技巧,他使用它来实现没有反射访问的结构类型,也就是吸血鬼方法 ):

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
  }
}

然后:

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)
               ^

我甚至没有检查任何封闭的树木。 请参阅我的博客文章了解此方法的实例。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM