gpt4 book ai didi

scala - 如何判断 Scala 宏的参数是否为函数?

转载 作者:行者123 更新时间:2023-12-04 04:32:33 26 4
gpt4 key购买 nike

我正在尝试编写一个对函数参数进行操作的宏。通过将参数设置为宏 Any,我很容易地处理了所有参数长度的匿名函数。然后匹配 Function(body, params) ,但我希望能够传递对函数变量的引用:

val valFunction = (something: Int) => (something * 3).toString
val functionVal = Macros.myMacro(valFunction)

我可以使用 WeakTypeTag s 根据 official documentation使用一个参数的函数来完成这项工作:
def myMacro[T, U](param: T => U) = macro myMacroImpl[T, U]

def myMacroImpl[T, U](c: Context)(param: c.Expr[T => U])
(implicit tt: c.WeakTypeTag[T], implicit ut: c.WeakTypeTag[T]) = {...}

但是宏只适用于一个参数的函数。我尝试检查一个名为“apply”的成员,它也是一个方法,但我遇到了删除问题,并且还担心重载方法等。我目前正在苦苦挣扎的解决方法是为 Function0 创建 23 个宏。通过 Function22 ,但是哎呀,我对此并不满意。我可以采取另一种方法吗?

最佳答案

解决此问题的一种可能方法是创建一个仅可用于函数的简单类型类:

trait Functionable[T]

使用实现隐式值的隐式宏:
object Functionable {
implicit def materialize[T]: Functionable[T] = macro materialize_impl[T]
def materialize_impl[T](c: Context)(implicit ttag: c.WeakTypeTag[T]): c.Expr[Functionable[T]] = {
val funcs = (0 to 22).map { c.universe.definitions.FunctionClass(_) }.toList
if (funcs.exists { ttag.tpe.typeSymbol == _ })
c.universe.reify { new Functionable[T] { } }
else {
c.abort(c.macroApplication.pos, "not a function")
}
}
}

这个特定的实现不适用于子类型,但如果需要更多,您可以自定义它。

然后我们可以定义一个宏:
def myMacro[T](f: T)(implicit functionable: Functionable[T]) = macro myMacroImpl[T]
def myMacroImpl[T](c: Ctx)(f: c.Expr[T])(functionable: c.Expr[Functionable[T]])(implicit ttag: c.WeakTypeTag[T]): c.Expr[String] = c.literal(ttag.tpe.toString)

此宏将仅针对函数展开,如果参数不是函数,则会因编译时隐式未找到错误而失败。使用宏,您可以通过函数类型的弱类型标签反射性地获取有关类型的信息。

Whole example can be found here .

关于scala - 如何判断 Scala 宏的参数是否为函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20344075/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com