在运行时获取 Scala 变量名称
是否可以在运行时获取 scala 变量的名称?
例如,是否可以编写一个函数 getIntVarName(variable: Int): String
,其行为如下?
val myInt = 3
assert("myInt" === getIntVarName(myInt))
Is it possible to get the name of a scala variable at runtime?
E.g. is it possible to write a function getIntVarName(variable: Int): String
behaving as follows?
val myInt = 3
assert("myInt" === getIntVarName(myInt))
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
对于您需要做的事情,在我看来,不需要运行时,因为您已经在编译时定义了 myInt 变量。如果是这种情况,您只需要通过宏进行一些 AST 操作。
请
注意,宏必须编译为单独的子项目,并且不能是必须应用宏替换的同一项目的一部分。检查此模板以了解如何定义此类宏子项目: https://github.com/echojc /scala-宏模板
For what you need to do, It seems to me that runtime is not required, since you already have your myInt variable defined at compile time. If this is the case, you just need a bit of AST manipulation via a macro.
Try
Be aware that macro's must be compiled as a separate subproject, and cannot be part of the same project where the macro substitution has to be applied. Check this template on how to define such a macro sub-project: https://github.com/echojc/scala-macro-template
您可以使用 scala-nameof 获取变量名称、函数名称、类成员名称或类型姓名。它发生在编译时,因此不涉及反射,也不需要运行时依赖。
将编译为:
You can use scala-nameof to get a variable name, function name, class member name, or type name. It happens at compile-time so there's no reflection involved and no runtime dependency needed.
will compile to:
基本上是做不到的。
JVM 不通过方法句柄提供任何内容(请记住,Scala 属性在字节码中被编码为方法以支持统一访问原则)。您可以获得的最接近的方法是使用反射来查找在特定类上定义的方法列表 - 我认为这对您的特定需求没有帮助。
可以将其实现为 Scala 功能,但需要编译器插件从 AST 中获取相关符号名称并将其作为字符串文字推送到代码中,因此我无法演示在一个简短的代码片段中:)
反射中经常出现的另一个命名问题是方法参数。至少这一点我可以帮忙。我这里有一个正在进行中的反射库,它基于编译器生成的 scala 签名,如下所示由
scalap
使用。它还远未准备好投入实际使用,但正在积极开发中。Basically, it can't be done.
The JVM offers nothing by way of a Method handle (remember, Scala properties are encoded as methods in bytecode to support the uniform access principle). The closest you can get is to use reflection to find a list of methods defined on a particular class - which I appreciate doesn't help with your particular need.
It is possible to implement this as a Scala feature, but it would require a compiler plugin to grab the relevant symbol name from the AST and push it into code as a string literal, so not something I could demonstrate in a short code snippet :)
The other naming problem that often comes up in reflection is method parameters. That one at least I can help with. I have a work-in-progress reflection library here that's based on the compiler-generated scala signature as used by
scalap
. It's nowhere near being ready for serious use, but it is under active development.在这样的元数据方面,Scala 还没有比 Java 更多的东西。密切关注 Scala Reflection 项目,但我怀疑它会很快提供对局部变量的访问。同时,请考虑使用字节码检查器库,例如 ASM。另一个重要的警告:局部变量名称在编译过程中会丢失,因此您需要在“调试”模式下编译以保留它们。
Scala doesn't yet have much more than Java in terms of metadata like this. Keep an eye on the Scala Reflection project, but I doubt that will offer access to local variables anytime soon. In the meantime, consider a bytecode inspector library like ASM. Another big caveat: local variable names are lost during compilation, so you'd need to compile in "debug" mode to preserve them.
我认为不可能获取变量的名称,但您可以使用对象尝试:
此打印:
class Test1$MyVar$2$
。这样你就可以从中得到“MyVar”。I don't think it's possible to get the name of a variable, but you can try it with objects:
This prints:
class Test1$MyVar$2$
. So you can get 'MyVar' out of it.这可以通过 Scala 3 宏来实现(在编译时完成)。
创建一个宏对象(必须位于单独的文件中):
然后您的类中需要一个内联方法。
并使用这种方法,例如:
参见官方文档: https:// docs.scala-lang.org/scala3/guides/macros/macros.html
This can be achieved with Scala 3 Macros (does it at compile time).
Create a Macro object (this must be in a separate file):
Then you need an
inline
method in your class.And use this method, like:
See the official documentation: https://docs.scala-lang.org/scala3/guides/macros/macros.html