在运行时获取Scala变量名称

use*_*071 11 scala

是否有可能在运行时获取scala变量的名称?

例如,是否可以编写getIntVarName(variable: Int): String如下函数?

val myInt = 3
assert("myInt" === getIntVarName(myInt))
Run Code Online (Sandbox Code Playgroud)

nat*_*usa 13

对于你需要做的事情,在我看来,运行时不是必需的,因为你已经在编译时定义了myInt变量.如果是这种情况,你只需要通过宏进行一些AST操作.

尝试

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"
  }
}
Run Code Online (Sandbox Code Playgroud)

请注意,宏必须编译为单独的子项目,并且不能是必须应用宏替换的同一项目的一部分.检查此模板,了解如何定义此类宏子项目: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
Run Code Online (Sandbox Code Playgroud)


Kev*_*ght 6

基本上,它无法完成.

JVM没有通过Method句柄提供任何内容(请记住,Scala属性被编码为字节码中的方法以支持统一访问原则).您可以获得的最接近的是使用反射来查找在特定类上定义的方法列表 - 我对此感到满意并不能满足您的特定需求.

可能实现这是一个Scala的功能,但它需要一个编译器插件从AST抢相应的符号名称,并将其推入代码作为字符串文字,所以不是我能在很短的代码片段展示:)

反射中经常出现的另一个命名问题是方法参数.那个至少我可以帮忙.我这里有一个正在进行中的反射库,它基于编译器生成的scala签名scalap.它还没有准备好认真使用,但它正在积极发展.


dwi*_*ern 5

您可以使用scala-nameof获得变量名称,函数名称,类成员名称或类型名称。它发生在编译时,因此不涉及反射,也不需要运行时依赖项。

val myInt = 3
assert("myInt" === nameOf(myInt))
Run Code Online (Sandbox Code Playgroud)

将编译为:

val myInt = 3
assert("myInt" === "myInt")
Run Code Online (Sandbox Code Playgroud)