问题描述
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")""")
}
我添加了返回类型。我假设fName
是编译时的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
。并且我添加了返回类型。同样重要的是,要创建的函数只能在宏扩展到的块内访问。新定义不是def macros的原意(macro annotations是)。
我不确定我是否完全了解您在做什么。如果您提供了如何使用宏的代码,则答案会更容易。