我想编写一个宏来获取类的属性名称。但不能在引用的语句中使用Symbol
模块。我收到吹气错误..。
inline def getProps(inline className: String): Iterable[String] = ${ getPropsImpl('className) }
private def getPropsImpl(className: Expr[String])(using Quotes): Expr[Iterable[String]] = {
import quotes.reflect.*
val props = '{
Symbol.classSymbol($className).fieldMembers.map(_.name) // error access to parameter x$2 from
} wrong staging level:
props - the definition is at level 0,
} - but the access is at level 1.
1条答案
按热度按时间cfh9epnr1#
宏有编译时和运行时。还有主代码的编译时和运行时。宏的运行时是主代码的编译时间。
是不正确的,因为Scala 3宏所做的是将树转换为树(例如,
Expr
转换为Expr
,Expr
是树上的 Package 器)(*)。那棵树在应用站点的范围内是没有意义的。
Symbol
、Symbol.classSymbol
等在这里是有意义的,在宏的范围内。也是不正确的,因为
className
作为一个值还不存在,它现在只是一棵树。我想正确的是使用
.valueOrAbort
用途:
(*)使用
c.eval
,Scala 2宏可以执行更多操作。在Scala3中也有类似的thingstaging.run
,但在宏中是被禁止的。实际上,
c.eval
(或禁用的staging.run
)也可以在Scala3中模拟get annotations from class in scala 3 macros