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?
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
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
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
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
::!#