Компиляция скриптов Scala. Как работает скрипт Scala?

Groovy

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

Scala поставляется с компилятором scalac,

Например, с тем же HelloWorld.scala сценарий:

println("Hello World")

Код не действителен для scalacпотому что компилятор ожидал определения класса или объекта, но работает в интерпретаторе Scala REPL. Как это возможно? Это обернуто в классе перед выполнением?

3 ответа

Решение

Код в Scala-Script сначала помещается в объект Scala, затем компилируется в JVM-Bytecode и, наконец, выполняется. Вы можете увидеть сгенерированный объект Scala, написав scala -Xprint:parser my_file.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()
      }
    }
  }
}

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, Запуск "интерпретатора" scala для файла, который содержит только println("Hello World") line в основном обернет его в объект (превратив его в первую форму, которую мы видели выше), скомпилирует и запустит для вас под капотом.

Обратите внимание, что (хотя код выглядит очень похоже на консольное приложение Hello World в Java), полученная скомпилированная программа - это не то же самое, что результат компиляции этой 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");
    }
}

Как только вы успешно скомпилируете файл с scalac, ты можешь использовать javapдизассемблером файла класса java для просмотра сгенерированных сигнатур классов и методов (Edit: спасибо @Luigi за указание на то, что он генерирует сигнатуры, а не код). То есть, scalac HelloWorld.scala с последующим javap HelloWorld,

Другие вопросы по тегам