在运行时获取 Scala 变量名称
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5050682/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Get Scala variable name at runtime
提问by user523071
Is it possible to get the name of a scala variable at runtime?
是否可以在运行时获取 scala 变量的名称?
E.g. is it possible to write a function getIntVarName(variable: Int): Stringbehaving as follows?
例如,是否可以编写一个getIntVarName(variable: Int): String行为如下的函数?
val myInt = 3
assert("myInt" === getIntVarName(myInt))
采纳答案by Kevin Wright
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.
JVM 不提供任何方法句柄(请记住,Scala 属性在字节码中编码为方法以支持统一访问原则)。您可以获得的最接近的是使用反射来查找在特定类上定义的方法列表 - 我认为这对您的特定需求没有帮助。
It ispossible 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 :)
这是可能实现这是一个Scala的功能,但它需要一个编译器插件从AST抢相应的符号名称,并将其推入代码作为字符串文字,所以不是我能在很短的代码片段展示:)
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 herethat'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 签名,如scalap. 它远未准备好正式使用,但正在积极开发中。
回答by natbusa
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.
对于您需要做的事情,在我看来,运行时不是必需的,因为您已经在编译时定义了 myInt 变量。如果是这种情况,您只需要通过宏进行一些 AST 操作。
Try
尝试
package com.natalinobusa.macros
import scala.language.experimental.macros
import scala.reflect.macros.blackbox.Context
object Macros {
// write macros here
def getName(x: Any): String = macro impl
def impl(c: Context)(x: c.Tree): c.Tree = {
import c.universe._
val p = x match {
case Select(_, TermName(s)) => s
case _ => ""
}
q"$p"
}
}
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
请注意,宏必须编译为单独的子项目,并且不能是必须应用宏替换的同一项目的一部分。检查这个模板如何定义这样一个宏子项目:https: //github.com/echojc/scala-macro-template
scala> import Macros._
import Macros._
scala> val myInt = 3
myInt: Int = 3
scala> "myInt" == getName(myInt)
res6: Boolean = true
回答by dwickern
You can use scala-nameofto 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.
您可以使用scala-nameof来获取变量名、函数名、类成员名或类型名。它发生在编译时,所以不涉及反射,也不需要运行时依赖。
val myInt = 3
assert("myInt" === nameOf(myInt))
will compile to:
将编译为:
val myInt = 3
assert("myInt" === "myInt")
回答by Adam Rabung
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.
在像这样的元数据方面,Scala 还没有比 Java 多得多。密切关注Scala Reflection 项目,但我怀疑它是否会在短期内提供对局部变量的访问。同时,考虑一个像ASM这样的字节码检查器库。另一个重要警告:局部变量名称在编译期间丢失,因此您需要在“调试”模式下编译以保留它们。
回答by Oleg Galako
I don't think it's possible to get the name of a variable, but you can try it with objects:
我认为不可能获得变量的名称,但您可以尝试使用对象:
object Test1 {
def main(args: Array[String]) {
object MyVar {
def value = 1
}
println(MyVar.getClass)
}
}
This prints: class Test1$MyVar$2$. So you can get 'MyVar' out of it.
这打印:class Test1$MyVar$2$。所以你可以从中得到“MyVar”。

