为什么运行时反射的宇宙和宏宇宙为scala创建两个不同的树?没有
如果我有一个转换代码的宏,如:
(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. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |