加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

scala – 宏返回类型取决于参数

发布时间:2020-12-16 09:06:44 所属栏目:安全 来源:网络整理
导读:我想写一个返回类型依赖于参数的宏.简化示例: def fun[T](methodName: String) = macro funImpl[T]def funImpl[T: WeakTypeTag](c: Context)(methodName: c.Expr[String]): /* c.Expr[T = return type of T.methodName] */ = { // return x = x.methodName}
我想写一个返回类型依赖于参数的宏.简化示例:

def fun[T](methodName: String) = macro funImpl[T]

def funImpl[T: WeakTypeTag](c: Context)(methodName: c.Expr[String]): /* c.Expr[T => return type of T.methodName] */ = {
  // return x => x.methodName
}

显然,注释掉的funImpl返回类型是非法的.我试过简单地返回一个树,但这会产生一个错误:

[error] macro implementation has wrong shape:
[error]  required: (c: scala.reflect.macros.Context): c.Expr[Any]
[error]  found   : (context: scala.reflect.macros.Context): context.Tree
[error] type mismatch for return type: c.universe.Tree does not conform to c.Expr[Any]
[error]     def fun[T] = macro PrivateMethodMacro.funImpl[T]
[error]                                          ^

有可能写这样的宏吗?显然,返回类型作为另一个类型参数传递是可能的,如Is it possible to write a scala macro whose returntype depends on argument?的答案,但这不是我想要的.

解决方法

是的,这是可能的,多亏了 whitebox macros的魔力:你可以告诉编译器返回类型是c.Expr [Any],它会推断出更精确的类型.

这种行为shocked me when I first ran into it-它非常非常强大且非常非常可怕 – 但它绝对是有意的,并且将继续得到支持,尽管2.11将区分whitebox和blackbox宏,前者可能仍处于实验状态更长的时间(如果他们完全离开的话).

例如,下面是你要求的快速草图(我在这里通过macro paradise plugin使用quasiquotes for 2.10,但如果没有quasiquotes,它只会更加冗长):

import scala.language.experimental.macros
import scala.reflect.macros.Context

def funImpl[T: c.WeakTypeTag](c: Context)(
  method: c.Expr[String]
): c.Expr[Any] = {
  import c.universe._

  val T = weakTypeOf[T]

  val methodName: TermName = method.tree match {
    case Literal(Constant(s: String)) => newTermName(s)
    case _ => c.abort(c.enclosingPosition,"Must provide a string literal.")
  }

  c.Expr(q"(t: $T) => t.$methodName")
}

def fun[T](method: String) = macro funImpl[T]

然后:

scala> fun[String]("length")
res0: String => Int = <function1>

您可以看到推断类型正是您想要的,而不是任何.您可以(也可能应该)将funImpl的返回类型设置为c.Expr [T =>任何]并返回类似c.Expr [T =>任何](q“_.$methodName”),但这基本上只是文档 – 它对在这种情况下如何推断宏的返回类型没有任何影响.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读