如何使用 scala 宏生成顶级 class/object

How to generate top-level class/object with scala macro

我们知道,在某些方法中使用 scala 宏很容易创建内部 class。 但我想知道是否可以生成顶级class/object? 如果答案是肯定的,那么如何避免生成相同的 class 两次? 我的 scala 版本是 2.11

  1. Top-level expansions must retain the number of annottees, their flavors and their names, with the only exception that a class might expand into a same-named class plus a same-named module, in which case they automatically become companions as per previous rule.

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. The Context.introduceTopLevel API, which used to be available in early milestone builds of Scala 2.11.0 as a stepping stone towards type macros, was removed from the final release, because type macros were rejected for including in Scala and discontinued in macro paradise.

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

Scala Macro: Define Top Level Object

introduceTopLevel has provided a long-requested functionality of generating definitions that can be used outside macro expansions. However, metaprogrammers have quickly discovered that introduceTopLevel is dangerous. Top-level scope is a resource shared between the typechecker and user metaprograms, so mutating it with introduceTopLevel can lead to compilation order problems. For example, if one file in a compilation run relies on definitions created by a macro expansion performed in another file, compiling the former before the latter may lead to unexpected compilation errors.

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

如果您要生成的随播广告已经存在,那么您在宏注释 macroTransform 中 return 的随播广告将替换原来的随播广告。你不需要注意会有两个 "companions",编译器会注意的。但如果是这种情况,通常情况下你肯定会匹配(无论只有注释者还是注释者 + 同伴)。