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

为什么运行时反射的宇宙和宏宇宙为scala创建两个不同的树?没有

发布时间:2020-12-16 09:15:40 所属栏目:安全 来源:网络整理
导读:如果我有一个转换代码的宏,如: (src: a.b.c.TestEntity) = { z.y.TestTable(None) } 要匹配该AST的无部分,我可以使用一个提取器,如: object NoneExtractor { def unapply(t: Tree): Boolean = t match { case Select(Ident(scala),none) if scala.encoded
如果我有一个转换代码的宏,如:

(src: a.b.c.TestEntity) =>
    {
      z.y.TestTable(None)
    }

要匹配该AST的无部分,我可以使用一个提取器,如:

object NoneExtractor {
    def unapply(t: Tree): Boolean = t match {
      case Select(Ident(scala),none) if scala.encoded == "scala" && none.encoded == "None" => true
      case _ => false
    }
  }

由于AST的无部分的显示如下:

Select(Ident(scala),None)

然而,如果我想编写一个单元测试的NoneExtractor我不想编译和重建宏,并在项目中托管测试宏正在编译.我想在宏的项目中对提取器进行单元测试,这表明运行时反射是一种方式:

val t = reify {

  (src: a.b.c.TestEntity) =>
    {
      z.y.TestTable(None)
    }

}.tree

然而树是完全不同的,在那棵树的showRaw中,None看起来像:

Ident(scala.None)

这是编写负面测试和检查我的宏的错误处理的坏消息.您不能使用来自另一个项目的宏来编写一个宏的负面测试,因为代码将无法编译(并且您无法使用编译错误调试负面测试).

为什么编译时反射和运行时反射之间的东西的表示方式根本不同?有没有办法在宏项目中创建可测试的树片段,这是在编译时反映的过程中将会传递给宏的相同的AST?

解决方法

为了解决这个不一致,你可以在你的模式匹配中使用即将到来的 quasiqoutes.它们抽象出AST,因此可以同时使用这两种表示形式(AST是编译器特定的,Scala是现在的单一编译器语言,但依靠编译器的内部表示方式并不好):

case q"_root_.scala.None" => ...

将匹配两个AST.此外,您可以使用q“_root_.scala.None”创建树,以便您不必担心表示.当quasiquotes与Scala 2.11发布时,Reify将会过时.要使用scala 2.10的quasiquote,您可以使用macro paradise.

Here is a nice WIP guide on scala quasiquotes.

(编辑:李大同)

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

    推荐文章
      热点阅读