【问题标题】:Is it possible to recover the name of the function from within the function in scala?是否可以从 scala 的函数中恢复函数的名称?
【发布时间】:2010-06-23 19:50:04
【问题描述】:

我想做类似的事情

def getMeASammy() {println "getMeASammy"}
def getMeADrink() {println "getMeADrink"}
def getMeASub() {println "getMeASub"}

但是,我不想明确输入函数的名称。

【问题讨论】:

  • 您可以使用堆栈跟踪,但在礼貌的公司中不应提及更多关于该主题的内容......
  • 我对 Scala 一无所知,但您不能为此使用 Java 反射 API 吗?参见例如Does Scala have introspection capable of something similar to Python's dir()?
  • 当有人问你的名字时,你会拿出你的钱包并检查你的身份证来回答吗?
  • @RandallSchulz 完全不相关。很高兴有这种东西来制作通用的测试例程。

标签: scala inspection


【解决方案1】:
scala> def currentMethodName() : String = Thread.currentThread.getStackTrace()(2).getMethodName
currentMethodName: ()String

scala> def getMeASammy() = { println(currentMethodName()) }
getMeASammy: ()Unit

scala> getMeASammy()
getMeASammy

【讨论】:

  • 我假设如果你执行 getStackTrace()(3) 你会得到调用它的函数?
  • 索引 (2) 或 (3) 会失败吗?前任。我应该做一个空检查吗?
  • @Raymond26 不,我认为这很安全。访问元素 2 意味着堆栈跟踪中必须至少存在三个方法,它们将是 - getStackTrace、调用 getStackTrace 的方法(此处为 currentMethodName)和调用该方法的方法(此处为 getMeASammy)。另外,必须调用 getMeASammy 才能执行它(即使它只是 REPL,如此处所示),所以是的,堆栈跟踪中会有第四项,是的,使用索引 3 是安全的。跨度>
【解决方案2】:

我写了一个simple library,它使用宏来获取函数的名称。如果您不介意额外的依赖,这可能是比使用 Thread.currentThread.getStackTrace()(2).getMethodName 更优雅的解决方案:

libraryDependencies += "com.github.katlasik" %% "functionmeta" % "0.2.3" % "provided"
import io.functionmeta._

def getMeASammy() {
   println(functionName) //will print "getMeASammy"
}

【讨论】:

    【解决方案3】:

    这有点令人反感,但唯一受支持的从 JVM 获取当前方法名称的方法是创建一个异常(但不抛出它),然后从异常的堆栈跟踪中读取方法名称。

    def methodName:String= new Exception().getStackTrace().apply(1).getMethodName()
    

    【讨论】:

    • 不需要创建异常。请参阅上面我的答案,它使用Thread.getStackTrace()。
    【解决方案4】:

    Nameof 正是这样做的,并且在编译时,因此没有创建异常、检查堆栈跟踪和其他反射式开销。

    nameof 自述文件中的相关示例:

    import com.github.dwickern.macros.NameOf._
    
      def startCalculation(value: Int): Unit = {
        println(s"Entered ${nameOf(startCalculation _)}")
      }
    
      // compiles to:
    
      def startCalculation(value: Int): Unit = {
        println(s"Entered startCalculation")
      }
    

    你的情况

    def getMeASammy() = println(nameOf(getMeASammy _))
    

    另外,nameOf 适用于类、类属性、类型等。

    【讨论】:

      猜你喜欢
      • 2016-06-22
      • 1970-01-01
      • 1970-01-01
      • 2015-06-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-05-31
      • 1970-01-01
      相关资源
      最近更新 更多