Scala println not working with App trait - scala

When I use the scala App trait, I can't get println to work.
This simple example prints as expected,
object HelloWorld {
def main(args: Array[String]) {
println("Hello, world!")
}
}
But once I introduce the trait it does not,
object HelloWorld extends App {
println("Hello, world!")
}
I get no errors but nothing prints to the console.

Did you compile it first (running scalac HelloWorld.scala)? See this comment: http://www.scala-lang.org/node/9483#comment-40627
Edited to add more explanation:
The first version actually was compiled. Scala files without an explicit main method are run uncompiled as scripts. That means that for your second version, the commands in the file are run sequentially, as though they had been entered into the interpreter--so, the object HelloWorld is created, but no method is called on it. There's more information about Scala as a scripting language here (scroll to Step 5): http://www.artima.com/scalazine/articles/steps.html

Add a line
object HelloWorld extends App {
/* code */
}
HelloWorld.main(args)
at the end of your file.
The Class defines the method but it need to be called too.

According to
http://www.scala-lang.org/api/current/scala/App.html
you want to do
object Main extends App {
Console.println("Hello World: " + (args mkString ", "))
}

Related

In Scala, multiple objects with main method can be present in a single file and run individually . What is the reason behind this?

I wrote below code in scala 3 in a single file
#main def main11 =
println("main11 printed something")
object Main10 extends App {
println("Main10 Executed !!".toUpperCase())
main11
}
object Main2 {
def main(args: Array[String]): Unit = {
println("Main2 can run too !!".toUpperCase())
Main10
}
}
It compiles fine and I can run any of these main11 Main2 Main10 in the IDE.
What is reason for this ?
Eg.
main11 output :
main11 printed something
Main2 output :
MAIN2 CAN RUN TOO !!
MAIN10 EXECUTED !!
main11 printed something
Usually in other languages I see 1 main class in 1 file.
Scala has idiomatic concepts which require multiple classes/objects/traits within the same file such as
companion objects
algebraic data types
However in general it is not best practice to define arbitrary multiple classes/objects/traits within the same file unless they are tightly related. The fact that your objects happen to have each a main method is not relevant as it is just considered a regular method.

Why IntelliJ doesn't run my script if it has main in it

I am observing an interesting behavior. I have an existing project in which I created a folder and created a Scala script in that folder. To run it I did
Write a Scala script, e.g. MyScript.scala
In the menu select: Run -> Edit Configurations... Press the "+" (⌘N also works on the Mac in this dialog) Select "Scala Script" Then select your Script file in this dialog
Interestingly, if the script is the following then I get error Scala script not found
object HelloWorld{
def main(args:Array[String]): Unit ={
println("hello world");
}
}
but if the script is
def greetings(): Unit ={
println("hello")
}
greetings();
then it works!
Why IntelliJ cannot run the 1st version of the script?
You could do the following:
Run it as a script.
You have to use the following code:
class HelloWorld {
def main(args:Array[String]): Unit ={
println("hello world");
}
}
object Foo extends HelloWorld
Foo.main(args)
Hint: I removed the 'build' action from 'Before launch' to show the warnings further down.
Run it as an Application.
You can keep your code. Just select 'Application' when creating the configuration.
object HelloWorld{
def main(args:Array[String]): Unit ={
println("hello world");
}
}
Why?
You have to provide an entry point for the script. So you could use the following code:
object HelloWorld {
def main(args:Array[String]): Unit ={
println("hello world");
}
}
HelloWorld.main(args) //without this line, Script is not found!
But this gives an error (expected class or object definition):
An If you try to extend from App trait, you get 2 warnings:
object HelloWorld extends App {
override def main(args:Array[String]): Unit ={
println("hello world");
}
}
HelloWorld.main(args)
So I guess its best to use one of two Solutions above.

Intellij - Run scala main file

I have installed Scala plugin and sbt executer in IntelliJ.
I have created a new Scala project and it created a build.sbt file.
In the project setting/Libraries I see a reference to the SBT I have on my computer.
I created a new Scala class with the following code:
class RunMe {
def main(args: Array[String]): Unit = {
println("Hello from main of class")
}
}
I can't seem to find a new type of run configuration to create for the scala class.
I don't see the green play button in the left column (IntelliJ Left Gutter)
What am I missing?
How can I configure a run configuration in the code?
Instead of a class with a static method, which is what you do in Java, you should use object in Scala:
object RunMe {
def main(args: Array[String]): Unit = {
println("Hello from main of class")
}
}
You can also mixin a trait called App instead of providing the main method:
object RunMe extends App {
println("Hello from main of class")
}
In both cases IntelliJ should pick the definition fine and offer you the green arrow to start the app.
I usually just mixin the App trait into my Runner object. Something like...
object RunMe extends App {
println("Hello from main of class")
}
should do the trick. Intellij should now pickup that this object is "runnable" and provide a "play" button as expected.

Run menu item disappear in IntelliJ

I have scala code in IntelliJ as follows:
HelloWorld.scala
object HelloWorld {
//var matchExample = new MatchExample()
def main(args: Array[String]) = {
printHello()
//matchExample.oddEven(1)
}
def printHello() = {
println("hello")
}
}
MatchExample.scala
class MatchExample {
def oddEven(x: Int): String = {
"Hello"
}
}
If I un-comment those two lines and try to do run by right-clicking in object I don't have Run menu item, but if I comment out those two lines then I do have "Run" menu item.
What I am missing?
The reason is that your main method signature(un-comment matchExample.oddEven(1)) is incompatible with what Scala compiler requires for a runnable program.
Yours is (args: Array[String])String, the runnable program's main method signature is (args: Array[String])Unit. If you run your code in Terminal, compiler will emit a warning.
allen:Desktop allen$ scalac HelloWorld.scala
HelloWorld.scala:1: warning: HelloWorld has a main method with
parameter type Array[String], but HelloWorld will not be a runnable program.
Reason: main method must have exact signature (Array[String])Unit
object HelloWorld {
^
one warning found
In Scala, if you wanna write a runnable program, you'd better use App trait.
The post has a detailed explaination on Scala App val initialization in main method.

Compiling Scala scripts. How works a Scala script?

Groovy
Groovy comes with a compiler called groovyc. For each script, groovyc generates a class that extends groovy.lang.Script, which contains a main method so that Java can execute it. The name of the compiled class matches the name of the script being compiled.
For example, with this HelloWorld.groovy script:
println "Hello World"
That becomes something like this code:
class HelloWorld extends Script {
public static void main(String[] args) {
println "Hello World"
}
}
Scala
Scala comes with a compiler called scalac.
For example, with the same HelloWorld.scala script:
println("Hello World")
The code is not valid for scalac, because the compiler expected class or object definition, but works in the Scala REPL Interpreter. How is possible? Is it wrapped in a class before the execution?
The code in a Scala-Script is first placed in a Scala object, then compiled to JVM-Bytecode and at last executed. You can see the generated Scala object by writing 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 will compile your code to java bytecode. println("Hello World") is not by itself a valid scala program, so scalac will not compile it.
You can do:
object Test extends App {
println("Hello World")
}
or
object Test {
def main(args: Array[String]) {
println("Hello World")
}
}
You can then run the output with scala Test.
Running the scala "interpreter" on a file that only contains the println("Hello World") line will basically wrap it in an object (transforming it into the first form we've seen above), compile it and run it for you under the hood.
Note that (even though the code looks very similar to a Hello World console application in java) the resulting compiled program is not the same thing that would result from the compilation of this 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");
}
}
Once you successfully compile a file with scalac, you can use javap, the java class file disassembler, to view the generated class and method signatures (Edit: thanks to #Luigi for pointing out that it is generated signatures, not code). That is, scalac HelloWorld.scala followed by javap HelloWorld.