Main method is not called in Scala script

2020-03-23 18:22发布

问题:

I am brand new to Scala, and I was wondering why the main method is not running in this script?

class Word {
}

object HelloWorld {
  def main(args: Array[String]) {
    println("Hello, world!")
  }
}

The interesting thing is that it works fine when i remove the Word class. Why is this? And how do I fix it?

回答1:

As shown in getting started with scala, you should explicitly invoke the main method, when running scala files as a script:

class Word {
}

object HelloWorld {
  def main(args: Array[String]) {
    println("Hello, world!")
  }
}

HelloWorld.main(args)

If you want to compile and run, you'll have to give the name of the object holding the main method:

scalac test.scala
scala HelloWorld


回答2:

The reason of this strange behavior is simple. When running the scala executable with a script name passed on the command line (as in scala hello.scala), what happens by default is that it will try to "guess" what to run. If the file contains only a single object with a suitable main method (meaning that it would also be a proper program entry point), that main method is run. Otherwise, the scala file is interpreted as a proper script (with statements accepted at the top level and run line by line, like in the interactive mode). So there really are 2 ways of running a scala file using the scala interpreter executable (the first one beig seldom used).

So as soon as you added another class to you source file, the first mode of execution (calling the main method) did not trigger anymore and you falled back to standard line by line interpretation. Thus your main method is not called anymore unless you explicitly call it.

For reference, here is the output of scala -help (emphasis mine):

Usage: scala <options> [<script|class|object|jar> <arguments>] or scala -help

All options to scalac (see scalac -help) are also allowed. The first given argument other than options to scala designates what to run. Runnable targets are:

  • a file containing scala source
  • the name of a compiled class
  • a runnable jar file with a valid Main-Class attribute
  • or if no argument is given, the repl (interactive shell) is started

Options to scala which reach the java runtime:

-Dname=prop passed directly to java to set system properties
-J -J is stripped and passed to java as-is
-nobootcp do not put the scala jars on the boot classpath (slower)

Other startup options:

-howtorun what to run (default: guess)
-i preload before starting the repl
-e execute as if entered in the repl
-save save the compiled script in a jar for future use
-nc no compilation daemon: do not use the fsc offline compiler

A file argument will be run as a scala script unless it contains only self-contained compilation units (classes and objects) and exactly one runnable main method. In that case the file will be compiled and the main method invoked. This provides a bridge between scripts and standard scala source.

Options for plugin 'continuations':
-P:continuations:enable Enable continuations



回答3:

Actually what you wrote is not a Scala script, but a simple Scala program. Scala scripts differs from simple programs in the way they are organized and run, there is no compilation stage, Scala compiler will interpret source file line by line, like in the REPL session.

To make a Scala script from your file just leave:

println("This is a scala script") 

and save it in *.scala file, then run it with scala command in the terminal window without any previous scalac call. Scala compiler will automatically determines that this is a script, because source file ends with an expression. When you place HelloWorld.main(args) at the end of your file, it will be executed as a script file, but the class and companion object with main() method are completely obsolete



回答4:

If you’re on some flavor of Unix, you can run a Scala script as a shell script by prepending a pound bang directive at the top of the file.

For example, type the following into a file named helloarg:

#!/bin/sh
exec scala "$0" "$@"
!#
// Say hello to the first argument
println("Hello, "+ args(0) +"!")

The initial #!/bin/sh must be the very first line in the file.
Once you set its execute permission:

$ chmod +x helloarg

You can run the Scala script as a shell script by simply saying:

$ ./helloarg globe

If you’re on Windows, you can achieve the same effect by naming the file helloarg.bat and placing this at the top of your script:

::#!
@echo off
call scala % 0 % *
goto :eof
::!#


标签: scala