Scala:是否可以使用宏注释来注释 class 的构造函数字段? (宏观天堂)
Scala: is it possible to annotate a constructor field of a class using a macro-annotation? (macro paradise)
我正在尝试使用宏注释来注释 class 的构造函数值。假设在 class 的 class 定义中实现并使用了一个名为 @identity
的宏注释 A:
class A(@identity val foo: String, // causes error
val bar: String) {
@identity val foobar: String = "" // doesn't cause error
}
当只是注释 foobar
时,一切都编译得很好。但是,注释 foo
时出现以下编译时错误:
没有同伴的顶级class只能扩展到同名class或包含同名同伴的块
有人可以详细说明此错误及其发生的原因吗?
我怀疑你调用了宏
import scala.annotation.{StaticAnnotation, compileTimeOnly}
import scala.language.experimental.macros
import scala.reflect.macros.whitebox
@compileTimeOnly("enable macro paradise to expand macro annotations")
class identity extends StaticAnnotation {
def macroTransform(annottees: Any*): Any = macro identity.impl
}
object identity {
def impl(c: whitebox.Context)(annottees: c.Tree*): c.Tree = {
import c.universe._
println(s"$annottees")
q"..$annottees"
}
}
喜欢
class A(@identity val foo: String,
val bar: String) {
@identity val foobar: String = ""
}
object A
那你有错误
Warning:scalac: List(<paramaccessor> val foo: String = _, class A extends scala.AnyRef {
<paramaccessor> val foo: String = _;
<paramaccessor> val bar: String = _;
def <init>(foo: String, bar: String) = {
super.<init>();
()
};
@new identity() val foobar: String = ""
}, object A extends scala.AnyRef {
def <init>() = {
super.<init>();
()
}
})
Warning:scalac:
Warning:scalac: List(<paramaccessor> val foo: String = _, def <init>(foo: String, bar: String) = {
super.<init>();
()
})
Warning:scalac: List(val foobar: String = "")
Error:(8, 12) top-level class with companion can only expand into a block consisting in eponymous companions
class A(@identity val foo: String,
Error:(8, 12) foo is already defined as value foo
class A(@identity val foo: String,
Error:(8, 12) foo is already defined as value foo
class A(@identity val foo: String,
问题是你拿了一个 class(可能还有伴生对象)和 return 不仅是它们还有 val foo
所以你改变了 top- 的 number/flavor被禁止的级别定义 https://docs.scala-lang.org/overviews/macros/annotations.html
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.
例如,如果我们更改宏
def impl(c: whitebox.Context)(annottees: c.Tree*): c.Tree = {
import c.universe._
println(s"$annottees")
q"..${annottees.tail}" // addded tail
}
然后一切都会编译。
我正在尝试使用宏注释来注释 class 的构造函数值。假设在 class 的 class 定义中实现并使用了一个名为 @identity
的宏注释 A:
class A(@identity val foo: String, // causes error
val bar: String) {
@identity val foobar: String = "" // doesn't cause error
}
当只是注释 foobar
时,一切都编译得很好。但是,注释 foo
时出现以下编译时错误:
没有同伴的顶级class只能扩展到同名class或包含同名同伴的块
有人可以详细说明此错误及其发生的原因吗?
我怀疑你调用了宏
import scala.annotation.{StaticAnnotation, compileTimeOnly}
import scala.language.experimental.macros
import scala.reflect.macros.whitebox
@compileTimeOnly("enable macro paradise to expand macro annotations")
class identity extends StaticAnnotation {
def macroTransform(annottees: Any*): Any = macro identity.impl
}
object identity {
def impl(c: whitebox.Context)(annottees: c.Tree*): c.Tree = {
import c.universe._
println(s"$annottees")
q"..$annottees"
}
}
喜欢
class A(@identity val foo: String,
val bar: String) {
@identity val foobar: String = ""
}
object A
那你有错误
Warning:scalac: List(<paramaccessor> val foo: String = _, class A extends scala.AnyRef {
<paramaccessor> val foo: String = _;
<paramaccessor> val bar: String = _;
def <init>(foo: String, bar: String) = {
super.<init>();
()
};
@new identity() val foobar: String = ""
}, object A extends scala.AnyRef {
def <init>() = {
super.<init>();
()
}
})
Warning:scalac:
Warning:scalac: List(<paramaccessor> val foo: String = _, def <init>(foo: String, bar: String) = {
super.<init>();
()
})
Warning:scalac: List(val foobar: String = "")
Error:(8, 12) top-level class with companion can only expand into a block consisting in eponymous companions
class A(@identity val foo: String,
Error:(8, 12) foo is already defined as value foo
class A(@identity val foo: String,
Error:(8, 12) foo is already defined as value foo
class A(@identity val foo: String,
问题是你拿了一个 class(可能还有伴生对象)和 return 不仅是它们还有 val foo
所以你改变了 top- 的 number/flavor被禁止的级别定义 https://docs.scala-lang.org/overviews/macros/annotations.html
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.
例如,如果我们更改宏
def impl(c: whitebox.Context)(annottees: c.Tree*): c.Tree = {
import c.universe._
println(s"$annottees")
q"..${annottees.tail}" // addded tail
}
然后一切都会编译。