【问题标题】:How do I get the current script or class name in Scala?如何在 Scala 中获取当前脚本或类名?
【发布时间】:2011-11-14 22:34:24
【问题描述】:

我希望我的 Scala 程序能够以编程方式确定其脚本文件名或类名,将字符串存储在变量 program 中并打印出名称。

Java 对此有 several 方法。

【问题讨论】:

  • 您是否尝试过采用您提到的 Java 解决方案?看起来他们都应该工作(?)

标签: class scala filenames


【解决方案1】:

我认为这是最简单的:

val program = new Exception().getStackTrace.head.getFileName

【讨论】:

    【解决方案2】:

    按照 0__ 的提示解析堆栈跟踪应该处理大多数用例,尤其是当具有 main 方法的对象不在同名文件中时:

    package utils
    
    trait ProgramInfo {
      val programInfo = try { 
        throw new RuntimeException("x")
      } catch { 
        case e: RuntimeException =>
          val arr = new java.io.CharArrayWriter()
          val buffer = new java.io.PrintWriter(arr)
          e.printStackTrace(buffer)
          val trace = arr.toString 
          val lines = io.Source.fromString(trace)
          val pat = """^.*at.*\.main\(([^:]*)(:.*)?\).*$""".r
          lines.getLines().collectFirst{case pat(n, l) => n}.getOrElse("<none>")
      }
    }
    
    object ProgramInfo extends ProgramInfo
    

    然后你这样称呼:

    println(utils.ProgramInfo.programInfo)
    

    或者你混入你的主要对象

    object A extends utils.ProgramInfo {
       def main(args: Array[String]) {
         println(programInfo)
       }
    }
    

    这适用于脚本scala A.script,无论代码是否包含在对象中。这也适用于使用scalac 编译并以scala A 运行时。使用 REPL 运行时,这将返回 &lt;none&gt;

    【讨论】:

    • 几乎有效。当我运行它时,它会打印空括号()
    • @mcandre,奇怪。我想在val trace 定义之后添加一个println(trace),看看.main(xxx) 是否出现在任何地方。
    • 啊,问题是我的抄写员错误。我尝试编写函数 def 来返回程序名称,但 Scala 将 defs 视为 void 函数。你知道的越多。
    • 另外,Scala 对package 声明不屑一顾。
    • @mcandre,哦,是的,包只适用于编译后的代码,不适用于 REPL。
    【解决方案3】:

    不完全确定您在寻找什么...

    $ scala -e 'println( "I am " + getClass.getName )'
    

    给我

    "I am Main$$anon$1"
    

    $ scala -e 'try { sys.error( "" )} catch { case e => println( "I am " + e.getStackTrace()( 3 ))}'
    

    给我

    "I am Main.main(scalacmd2873893687624153305.scala)"
    

    【讨论】:

    • 例如,如果我们有一个程序 Hello.scala,我想以编程方式在 Hello#main 中检测类名是“Hello”,将其保存到变量 program,然后打印出来出来。
    • @mcandre 在 Scala 中,您不会在类中运行 main 方法,而是在对象中运行它。如果您从类实例调用,上面的getClass.getName 将起作用。 (它也可以在对象中工作,但看起来可能与您期望的不太一样。)
    【解决方案4】:
    // With help from huynhjl
    // http://stackoverflow.com/questions/8129185#8131613
    
    import scala.util.matching.Regex.MatchIterator
    
    object ScriptName {
        val program = {
            val filenames = new RuntimeException("").getStackTrace.map { t => t.getFileName }
            val scala = filenames.indexOf("NativeMethodAccessorImpl.java")
    
            if (scala == -1)
                "<console>"
            else
                filenames(scala - 1)
        }
    
        def main(args: Array[String]) {
            val prog = program
            println("Program: " + prog)
        }
    }
    

    Rosetta Code

    【讨论】:

      【解决方案5】:
      #!/bin/bash
      exec scala "$0" "$0" "$@"
      !#
      
      val program = args(0)
      println(program)
      

      【讨论】:

      • 感谢您的代码 sn-p。您能否编写它以便它也可以与scalac 一起编译?
      猜你喜欢
      • 2017-09-09
      • 2023-02-09
      • 2011-05-12
      • 2011-05-08
      • 1970-01-01
      • 2011-01-07
      • 2013-03-16
      • 1970-01-01
      • 2011-01-12
      相关资源
      最近更新 更多