scala - 如何使用 scala 宏生成顶级类/对象
问题描述
众所周知,使用 scala 宏在某些方法中很容易创建内部类。但我想知道是否可以生成顶级类/对象?如果答案是肯定的,那么如何避免两次生成同一个类呢?我的斯卡拉版本是 2.11
解决方案
- 顶级扩展必须保留注释者的数量、他们的风格和他们的名字,唯一的例外是一个类可能会扩展成一个同名的类和一个同名的模块,在这种情况下,它们会按照之前的规则自动成为同伴.
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
但它被删除了。
Context.introduceTopLevel
. 该Context.introduceTopLevel
API 曾在 Scala 2.11.0 的早期里程碑版本中作为类型宏的垫脚石提供,但已从最终版本中删除,因为类型宏因包含在 Scala 中而被拒绝并在宏天堂中停止使用。
https://docs.scala-lang.org/overviews/macros/changelog211.html
introduceTopLevel
提供了一个长期需要的生成定义的功能,可以在宏扩展之外使用。然而,元程序员很快发现这introduceTopLevel
是危险的。顶级范围是类型检查器和用户元程序之间共享的资源,因此对其进行变异可能introduceTopLevel
会导致编译顺序问题。例如,如果编译运行中的一个文件依赖于在另一个文件中执行的宏扩展创建的定义,则在后者之前编译前者可能会导致意外的编译错误。
https://infoscience.epfl.ch/record/226166/files/EPFL_TH7159.pdf(第 5.2.3 节结论)
如果您要生成的伴侣已经存在,那么您在宏注释中返回的伴侣macroTransform
将替换原始伴侣。你不需要注意会有两个“同伴”,编译器会注意的。但如果是这种情况,通常情况下你肯定会匹配(无论是否只有 annottee 或 annottee + 同伴)。
推荐阅读
- nginx - 使用 Cloudflare 的入口 SSL/TLS 配置
- reactive-programming - 打印日志时,项目反应器始终在主线程中运行
- windows - 在 Windows 的 docker 日志中搜索字符串
- django - 如何将 django html 模板呈现为纯文本?
- javascript - 在计数器达到零后,如何使页面的背景变为红色?
- td-engine - 有没有办法删除TDengine中的数据?
- vue.js - v-bind:src 属性不适用于 v-for
- angular - 自新版本以来的 WordPress + Capacitor CORS 问题
- javascript - 如何构造一个包含对象数组的输出?
- javascript - 如何在 ReactJS APP 中调用预训练的 Magenta Tensorflow JS 任意样式迁移模型?