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

在reify子句中如何使用Scala Macro中计算的类型?

发布时间:2020-12-16 09:14:59 所属栏目:安全 来源:网络整理
导读:我一直在使用 Scala宏,并在宏中包含以下代码: val fieldMemberType = fieldMember.typeSignatureIn(objectType) match { case NullaryMethodType(tpe) = tpe case _ = doesntCompile(s"$propertyName isn't a field,it must be another thing") } reify{ ne
我一直在使用 Scala宏,并在宏中包含以下代码:

val fieldMemberType = fieldMember.typeSignatureIn(objectType) match {
      case NullaryMethodType(tpe)   => tpe
      case _                      => doesntCompile(s"$propertyName isn't a field,it must be another thing")
    }

    reify{
      new TypeBuilder() {
        type fieldType = fieldMemberType.type
      }
    }

你可以看到,我设法得到一个c.universe.Type fieldMemberType.这表示对象中某个字段的类型.一旦我得到了,我想在reify中创建一个新的TypeBuilder对象. TypeBuilder是一个抽象类,带有抽象参数.这个抽象参数是fieldType.我想要这个fieldType是我之前发现的类型.

运行这里显示的代码返回一个未找到的fieldMemberType.有什么办法可以让fieldMemberType在reify子句中工作吗?

解决方法

问题是,您传递给reify的代码本质上将被逐字地放置在宏被扩展的位置,fieldMemberType不会意味着任何东西.

在某些情况下,您可以使用拼接将您在宏扩展时间的表达式潜入到您所接受的代码中.例如,如果我们尝试创建一个这个特征的实例:

trait Foo { def i: Int }

在宏扩展时间里有这个变量:

val myInt = 10

我们可以写下列内容:

reify { new Foo { def i = c.literal(myInt).splice } }

这不会在这里工作,这意味着你将不得不忘记好的小细节,并用手写出AST.你会发现这很多,不幸的是.我的标准方法是启动一个新的REPL并输入如下内容:

import scala.reflect.runtime.universe._

trait TypeBuilder { type fieldType }

showRaw(reify(new TypeBuilder { type fieldType = String }))

这将会吐出几行AST,然后您可以剪切并粘贴到您的宏定义中作为起点.然后你把它弄干净,换成这样的东西:

Ident(TypeBuilder)

有了这个:

Ident(newTypeName("TypeBuilder"))

和FINAL与Flag.FINAL等等.我希望AST类型的toString方法更准确地对应于构建它们所需的代码,但是您可以很快地了解需要更改的内容.你会得到这样的结果:

c.Expr(
  Block(
    ClassDef(
      Modifiers(Flag.FINAL),anon,Nil,Template(
        Ident(newTypeName("TypeBuilder")) :: Nil,emptyValDef,List(
          constructor(c),TypeDef(
            Modifiers(),newTypeName("fieldType"),TypeTree(fieldMemberType)
          )
        )
      )
    ),Apply(Select(New(Ident(anon)),nme.CONSTRUCTOR),Nil)
  )
)

其中anon是您为您的匿名类提前创建的类型名称,构造函数是一种方便的方法,可用于使此类事物变得更不可怕(您可以在this complete working example年底找到其定义).

现在,如果我们将这个表达式包含在像this这样的表达式中,我们可以写下列内容:

scala> TypeMemberExample.builderWithType[String]
res0: TypeBuilder{type fieldType = String} = $1$$1@fb3f1f3

所以它的工作.我们已经使用了c.universe.Type(我从builderWithType中的类型参数的WeakTypeTag获得),但它可以与任何旧类型完全相同的方式工作),并用它来定义TypeBuilder的类型成员特征.

(编辑:李大同)

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

    推荐文章
      热点阅读