首页 > 解决方案 > 如何使用 scala 宏生成顶级类/对象

问题描述

众所周知,使用 scala 宏在某些方法中很容易创建内部类。但我想知道是否可以生成顶级类/对象?如果答案是肯定的,那么如何避免两次生成同一个类呢?我的斯卡拉版本是 2.11

标签: scalascala-macros

解决方案


  1. 顶级扩展必须保留注释者的数量、他们的风格和他们的名字,唯一的例外是一个类可能会扩展成一个同名的类和一个同名的模块,在这种情况下,它们会按照之前的规则自动成为同伴.

https://docs.scala-lang.org/overviews/macros/annotations.html

所以你可以转换顶层

@annot
class A

进入

class A
object A

或者

@annot
object A

进入

class A
object A

也存在,c.introduceTopLevel但它被删除了。

  1. Context.introduceTopLevel. 该Context.introduceTopLevelAPI 曾在 Scala 2.11.0 的早期里程碑版本中作为类型宏的垫脚石提供,但已从最终版本中删除,因为类型宏因包含在 Scala 中而被拒绝并在宏天堂中停止使用。

https://docs.scala-lang.org/overviews/macros/changelog211.html

Scala 宏:定义顶级对象

introduceTopLevel提供了一个长期需要的生成定义的功能,可以在宏扩展之外使用。然而,元程序员很快发现这introduceTopLevel是危险的。顶级范围是类型检查器和用户元程序之间共享的资源,因此对其进行变异可能 introduceTopLevel会导致编译顺序问题。例如,如果编译运行中的一个文件依赖于在另一个文件中执行的宏扩展创建的定义,则在后者之前编译前者可能会导致意外的编译错误。

https://infoscience.epfl.ch/record/226166/files/EPFL_TH7159.pdf(第 5.2.3 节结论)

如果您要生成的伴侣已经存在,那么您在宏注释中返回的伴侣macroTransform将替换原始伴侣。你不需要注意会有两个“同伴”,编译器会注意的。但如果是这种情况,通常情况下你肯定会匹配(无论是否只有 annottee 或 annottee + 同伴)。


推荐阅读