首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >scala 3宏:获取类属性

scala 3宏:获取类属性
EN

Stack Overflow用户
提问于 2022-03-31 06:39:29
回答 1查看 182关注 0票数 0

我想要写一个宏来获取类的属性名。但不能在引号语句中使用Symbol模块。我被吹错了..。

代码语言:javascript
运行
复制
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.
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-09-19 12:54:00

宏有编译时间和运行时。主代码有编译时间和运行时间。宏的运行时是主代码的编译时间。

代码语言:javascript
运行
复制
def getPropsImpl... = 
  '{ Symbol.classSymbol($className).fieldMembers.map(_.name) }
  ...

是不正确的,因为Scala 3宏所做的是将树转换为树(即Exprs转换为Exprs,Expr是树的包装器) (*)。树

代码语言:javascript
运行
复制
Symbol.classSymbol($className).fieldMembers.map(_.name)

将没有意义的范围内的应用网站。在宏的范围内,SymbolSymbol.classSymbol等都是有意义的。

代码语言:javascript
运行
复制
def getPropsImpl... = 
  Symbol.classSymbol(className).fieldMembers.map(_.name)
  ...

这也是不正确的,因为className作为一个值还不存在,它现在只是一棵树。

我想对.valueOrAbort是正确的

代码语言:javascript
运行
复制
import scala.quoted.*

inline def getProps(inline className: String): Iterable[String] = ${getPropsImpl('className)}

def getPropsImpl(className: Expr[String])(using Quotes): Expr[Iterable[String]] = {
  import quotes.reflect.*

  Expr.ofSeq(
    Symbol.classSymbol(className.valueOrAbort).fieldMembers.map(s =>
      Literal(StringConstant(s.name)).asExprOf[String]
    )
  )
}

用法:

代码语言:javascript
运行
复制
// in other file
getProps("mypackage.App.A") //ArraySeq(s, i)

// in other subproject
package mypackage
object App {
  case class A(i: Int, s: String)
}

(*) Scala 2宏可以使用c.eval做更多的事情。在Scala 3中,有类似的事情 staging.run,但是在宏中是已禁用

实际上,c.eval (或禁止的staging.run)也可以在Scala 3中进行模拟。

从scala 3宏的类中获取注释

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71687957

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档