Object extends App or Object + def main(...)? [duplicate] - scala

What is the difference between
object Application extends App {
println("Hello World")
}
and
object Application {
def main(args: Array[String]): Unit = {
println("Hello World");
}
}

The App trait is a convenient way of creating an executable scala program. The difference to the main method altenative is (apart from the obvious syntactic differences) that the App trait uses the delayed initalization feature.
From the release notes for 2.9 (see http://www.scala-lang.org/old/node/9483 )
Objects inheriting the App trait instead make use of Scala 2.9’s delayed initialization feature to execute the whole body as part of an inherited main method.
Another new feature of the App scheme is that command line arguments are now accessible via the args value (which is inherited from trait App)

These two cases is not same on the scala scripting.
object extends App was not executed by "scala MyObject.scala" command,
but the object containing the main method was executed by "scala MyObject.scala" command.
Which was described as scala looking for object with main method for scripting.
When using REPL or scala workseet of Eclipse,
need to call MyObject.main(Array[String]()) explicitly for both cases.
This simple tip be helpful for beginner like me.

App trait is implemented using the [[DelayedInit]] functionality, which means that fields of the object will not have been initialized before the main method has been executed.

Related

Cannot run scala in IntelliJ

I'm struggling with running Scala Hello World project using IntelliJ IDEA Scala plugin. The project is created without any problems but when I create function which should be run, the run button doesn't appear. I've got no idea why it doesn't work.
Version of IntelliJ - 2020.3.1 (Community Edition)
Version of Scala plugin 2020.3.18
I've created Scala/sbt project (I'd also tried Scala/IDEA)
Vanilla options (but I'd also tried other versions of JDK, Scala and sbt)
The run button is missing
My code is:
class Hello extends App {
println("Hello world")
}
I've tried creating Scala worksheet and It works.
When you extend App, it needs to be as object Main extends App, not class Main extends App.
See Scala 2.13 specification 9.5 (emphasis mine):
A program is a top-level object that has a member method main of type (Array[String])Unit
The main method of a program can be directly defined in the object, or it can be inherited. The scala library defines a special class scala.App whose body acts as a main method
As Suma mentioned in his answer, you should use object, and not class. The code of the Hello file should be:
object Hello {
def main(args: Array[String]): Unit = {
println("Hello world")
}
}
As stated in YOUR FIRST LINES OF SCALA. Please note that if you prefer to extend App, all of the statements will be executed, as stated in the last link:
The argument of the scala command has to be a top-level object. If that object extends trait scala.App, then all statements contained in that object will be executed; otherwise you have to add a method main which will act as the entry point of your program.
Which means you have another option:
object Hello extends App {
println("Hello world")
}
I have created a gif that shows an example.

Why we need lazy evaluation by extending App trait in Scala?

Now i understand how my program runs after extending App trait .I went through this link to understand how App trait works . In the link it is mentioned that by extending App trait we are achieving lazy evaluation . Why i would need lazy evaluation ? How lazy evaluation better than direct call to main() instead of extending App trait ?
I think it's the other way around: we don't need lazy eval, but we use it behind the scenes because that's the only way to implement it. From the scaladoc:
The App trait can be used to quickly turn objects into executable
programs.
By using App trait you avoid the boilerplate of writing:
object MainApp {
def main(args: Array[String]): Unit = { ... }
}
There is no way to achieve this syntax: object MainApp extends App {...} with regular means because you would have to override main method to call your code. Thus you can use compiler trick with DelayedInit which will turn your object body into a function call which will be called from main - this is the way to connect your code to the main entry point.
The caveat mentioned by scaladoc is:
It should be noted that this trait is implemented using the
[[DelayedInit]] functionality, which means that fields of the object
will not have been initialized before the main method has been
executed.
which for me personally is a preferred way of doing things. This, in contrast, is different from static initializers in Java that are executed before main method is called.

Run class in Scala IDE

I just installed the Eclipse Scala IDE and imported some existing projects. However, when I want to run the classes (that contain a main def) via right click -> Run, I only get 'Run configurations...'. How can I run these Scala classes?
(I already checked that the 'Scala Nature' is added.)
You need to run an object not a class as noted by urban_racoons. so you can run either:
object MyApp{
def main(args: Array[String]): Unit = {
println("Hello World")
}
}
or
object MyApp extends App {
println("Hello World")
}
Scala can not run a class because the main method needs to be static. Which can only be created behind the scenes by the compiler from a singleton object in Scala. Create the object and "run as a Scala application" should appear in the "run" context sub menu as long as you have the Scala perspective open.
You can still access the programme's arguments using the App trait as in
object MyApp extends App {
println("The programme arguments are:")
args.foreach(println)
// the above is just shorthand for
// args.foreach(ar => println(ar))
}
It should also be noted that App is a trait. So it can be mixed in with other traits and any class, which makes it handy for rapid prototyping.

Difference between using App trait and main method in scala

What is the difference between
object Application extends App {
println("Hello World")
}
and
object Application {
def main(args: Array[String]): Unit = {
println("Hello World");
}
}
The App trait is a convenient way of creating an executable scala program. The difference to the main method altenative is (apart from the obvious syntactic differences) that the App trait uses the delayed initalization feature.
From the release notes for 2.9 (see http://www.scala-lang.org/old/node/9483 )
Objects inheriting the App trait instead make use of Scala 2.9’s delayed initialization feature to execute the whole body as part of an inherited main method.
Another new feature of the App scheme is that command line arguments are now accessible via the args value (which is inherited from trait App)
These two cases is not same on the scala scripting.
object extends App was not executed by "scala MyObject.scala" command,
but the object containing the main method was executed by "scala MyObject.scala" command.
Which was described as scala looking for object with main method for scripting.
When using REPL or scala workseet of Eclipse,
need to call MyObject.main(Array[String]()) explicitly for both cases.
This simple tip be helpful for beginner like me.
App trait is implemented using the [[DelayedInit]] functionality, which means that fields of the object will not have been initialized before the main method has been executed.

In Scala static value initialization does not appear to be happening before the main method is called

My Scala version:
Scala code runner version 2.9.0.1 -- Copyright 2002-2011, LAMP/EPFL
Given this code in a file named Static.scala:
object Main extends App {
val x: String = "Hello, World!"
override def main(args: Array[String]): Unit = {
println(x)
}
}
When I run:
scalac Static.scala && scala Main
I see:
null
instead of:
Hello, World!
I thought that x was a static because it was defined in an object, and that it would be initialized prior to the main method being called.
What am I doing wrong? Thanks!
This happens because of how you used the App trait. The App trait uses the DelayedInit feature which changes how the class body (including field initialization) is executed. The App trait includes a main method which executes the class body after binding the args field to the arguments to the program. Since you have overridden main this initialization is not happening. You should not provide a main method when using the App trait. You should either put the application code directly in the class body or not inherit from the App trait.
Try
lazy val x = "Hello World"
That should give you the results you're expecting.
You are not support to have a main method on an object extending App. If you do override it, you'd better understand how, exactly, DelayedInit works. In particular, objects extending App do not have static initialization -- that's the whole point of App.