【问题标题】:Compiling Scala scripts. How works a Scala script?编译 Scala 脚本。 Scala 脚本如何工作?
【发布时间】:2012-03-19 17:17:07
【问题描述】:

时髦

Groovy 带有一个名为groovyc 的编译器。对于每个脚本,groovyc 生成一个扩展 groovy.lang.Script 的类,其中包含一个 main 方法,以便 Java 可以执行它。编译后的类名与正在编译的脚本名相匹配。

例如,使用这个HelloWorld.groovy 脚本:

println "Hello World"

变成这样的代码:

class HelloWorld extends Script {
    public static void main(String[] args) {
        println "Hello World"
    }
}

斯卡拉

Scala 带有一个名为 scalac 的编译器。

例如,使用相同的HelloWorld.scala 脚本:

println("Hello World")

代码对scalac 无效,因为编译器需要类或对象定义,但在 Scala REPL 解释器中有效。怎么可能?执行前是否封装在一个类中?

【问题讨论】:

  • 您是在问scalac 生成了哪些Java 代码?您确定scalac 实际生成Java 代码吗?我假设它直接生成 Java 字节码(即.class 文件)。
  • println("Hello World") 不是有效的 scala 类,因此 scalac 将拒绝编译它(尽管 scala REPL 会“解释”它)
  • 我认为这里存在一个普遍的理解问题。 Scala 不是脚本语言,所以没有 Scala 脚本。 Scala 是一种静态类型的编程语言,可以编译为 jvm 字节码。
  • @drexin 请参阅 Odersky 等人的 Scala 编程 的第 2 章第 4 节,“编写一些 Scala 脚本”...我想他们会不同意 :)不过,您不要使用scalac
  • @LuigiPlinge 好吧,你是对的 ;-)。

标签: scala groovy jvm-languages scalac scala-script


【解决方案1】:

Scala-Script 中的代码首先放置在 Scala 对象中,然后编译为 JVM-Bytecode,最后执行。写scala -Xprint:parser my_file.scala可以看到生成的Scala对象:

package <empty> {
  object Main extends scala.ScalaObject {
    def <init>() = {
      super.<init>();
      ()
    };
    def main(argv: Array[String]): scala.Unit = {
      val args = argv;
      {
        final class $anon extends scala.AnyRef {
          def <init>() = {
            super.<init>();
            ()
          };
          println("hello world")
        };
        new $anon()
      }
    }
  }
}

【讨论】:

    【解决方案2】:

    scalac 会将您的代码编译为 java 字节码。 println("Hello World") 本身不是一个有效的 scala 程序,所以 scalac 不会编译它。 你可以这样做:

    object Test extends App {
      println("Hello World")
    }
    

    object Test {
      def main(args: Array[String]) {
        println("Hello World")
      }
    }
    

    然后您可以使用scala Test 运行输出。 在仅包含 println("Hello World") 行的文件上运行 scala“解释器”基本上会将其包装在一个对象中(将其转换为我们在上面看到的第一种形式),编译它并在引擎盖下为您运行它。

    请注意(即使代码看起来非常类似于 java 中的 Hello World 控制台应用程序)生成的编译程序与编译此 java 产生的结果相同

    /*  note: this is Java code */
    /* this does NOT compile to the same bytecode as the previous scala example*/
    public class Test {
        public static void main (String args[]) {
            System.out.println ("Hello World");
        }
    }
    

    【讨论】:

      【解决方案3】:

      使用scalac成功编译文件后,可以使用java类文件反汇编器javap查看生成的类和方法签名(编辑:感谢@Luigi指出它是生成的签名,而不是代码)。即scalac HelloWorld.scala 后跟javap HelloWorld

      【讨论】:

      • 它不会显示生成的代码。它只是向您显示类和方法签名。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多