Scala 宏调用编译时确定的函数名

Scala macros invoke a compile-time determined function name

我有以下代码:

def invokeFunction(logger: Logger, fName: String) = macro invokeFunctionImpl

//...

def invokeFunctionImpl(c: Context)(logger: c.Expr[Logger], fName: c.Expr[String]) ={
  import c.universe._
  // i'd like to invoke: logger.${fName}("some message")
}

我面临的另一个问题是在编译时使用给定参数命名函数:

def createFunction(fName: String) = macro createFunctionImpl

//...

def createFunctionImpl(c: Context)(fName: c.Expr[String], param: c.Expr[String]) ={
  import c.universe._
  // i'd like to create: def functionNamed${fName}(param: [paramType]) = {
    // implementation unimportant
}

如有任何帮助,我们将不胜感激。

invokeFunction 应该是

def invokeFunction(logger: Logger, fName: String): Unit = macro invokeFunctionImpl

def invokeFunctionImpl(c: blackbox.Context)(logger: c.Expr[Logger], fName: c.Expr[String]): c.Expr[Unit] ={
  import c.universe._
  val q"${fNameStr: String}" = fName.tree
  c.Expr(q"""$logger.${TermName(fNameStr)}("some message")""")
}

我添加了 return 类型。我假设 fName 是 compile-time String 文字(否则你会得到 MatchError)。

关于createFunction尝试

def createFunction(fName: String, param: String): Unit = macro createFunctionImpl

def createFunctionImpl(c: blackbox.Context)(fName: c.Expr[String], param: c.Expr[String]): c.Expr[Unit] ={
  import c.universe._
  val q"${fNameStr: String}" = fName.tree
  val q"${paramNameStr: String}" = param.tree

  c.Expr(q"""
    def ${TermName(fNameStr)}(${TermName(paramNameStr)}: ParamType) = ???

    ()
  """)
}

请注意宏的签名和它的实现必须一一对应。所以我将 param 添加到 createFunction。我添加了 return 类型。同样重要的是,正在创建的函数只能在我们的宏扩展到的块内访问。新定义不是 def macros are normally intended for (macro annotations 的定义)。

我不确定我是否完全理解你在做什么。如果您提供您将如何使用宏的代码,将更容易回答。