Using an object inside a class in same scala file - scala

The following is the example that I am working on,
package com.sandbox.scala
class ScalaOne {
def main(args: Array[String]){
com.sandbox.scala.sayHello.hello(); //This works
sayHello.hello(); //error: not found: value sayHello
}
}
object sayHello{
def hello(){
println("Hello from Scala");
}
}
As you may see the second call sayHello.hello() throws an error mentioned in the comment. Why is that? I assumed it should work.

Related

Why the main method cant be loaded

I would like to run the simple example mentioned below. Eclipse generates an error reading:
main class can't be found or loaded
Please let me know how to fix this error and describe why it happens.
Main.kt
class Main {
fun main(args: Array<String>) {
println("Hello, World!")
}
}
The issue with your code is that the main function is not static.
To make it static, either put it out of the class (the recommended way):
fun main(args: Array<String>) {
println("Hello, World!")
}
Or use #JvmStatic annotation:
object Main {
#JvmStatic
fun main(args: Array<String>) {
println("Hello, World!")
}
}
Note that statics can only appear in objects. However, I am not sure that JVM will recognize such main method. It seems to be working as well:

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.

Scala compile time error while calling a method by passing List[Record]

I am doing some basic handson in scala.. i am getting compile-time error at the place of defining a method called processList.
The compile time error is
Multiple markers at this line:
- only classes can have declared but undefined
members
My code is as follows,
package pack1
import scala.io.Source
case class Record(id:Int, name:String, city:String)
object ReadingFile {
def main(args: Array[String]): Unit = {
val fileLoc:String = "/home/edureka/surender/inputfiles/records.txt"
val fileData:List[String] = Source.fromFile(fileLoc).getLines().toList
val fileList =fileData.map { eachLine => {
val Array(a:String,b:String,c:String) = eachLine.split(",")
Record(a.toInt,b,c)
} }
println(fileList)
processList(fileList)
}
def processList(myList:List[Record])
{
}
}
I dont know how to fix this, Can somebody help me on this?
Because of the new line after def processList(myList:List[Record]) Scala compiler thinks that the method implementation is not given and below block {} does not belong to the method. So compiler thinks its a abstract method.
Declare processList like this
def processList(myList:List[Record]) {
}
or
def processList(myList:List[Record]): Unit = {
}
Instead of this
def processList(myList:List[Record])
//remove this line to fix the error
{
}
The problem with this code is here,
def processList(myList:List[Record])
// <------ Notice this blank line
{
}
This leads the compiler to think that these are two different statements. And hence it thinks that you have left def processList(myList:List[Record]) without providing an implementation. And a class or case class and object can not have un-implemented members.
So... just fix that,
def processList(myList:List[Record]): Unit = {
}

scala command skips running main if class outside of singleton object

EDIT: Main method is not called in Scala script is related (in particular, the answer from Régis Jean-Gilles). This post gives more details to describe the issue. And the answer (by suish) give a more practical demonstration to explain the behaviour of the scala command.
Content of MiniScalaApp.scala
object MiniScalaApp {
def main(args: Array[String]) = {
println(s"Scala Version: ${scala.util.Properties.scalaPropOrElse("version.number", "unknown")}")
println(new Dinosaur("Tyrannotitan", 4900))
println(new Dinosaur("Animantarx ", 300))
}
class Dinosaur (name:String, weightKG: Int) {
override def toString = f"$name, Weight: $weightKG kg"
}
}
Executed at the command line by:
$ scala /myProject/src/main/scala/MiniScalaApp.scala
Produces the expected output:
Scala Version: 2.11.7
Tyrannotitan, Weight: 4900 kg
Animantarx, Weight: 300 kg
However, if the Dinosaur class is placed outside of the singleton object MiniScalaApp then the scala command produces no console output, no error message.
object MiniScalaApp {
def main(args: Array[String]) = {
println(s"Scala Version: ${scala.util.Properties.scalaPropOrElse("version.number", "unknown")}")
println(new Dinosaur("Tyrannotitan", 4900))
println(new Dinosaur("Animantarx ", 300))
}
}
class Dinosaur (name:String, weightKG: Int) {
override def toString = f"$name, Weight: $weightKG kg"
}
In this 2nd version, to get the console output, the code must be compiled first and then run the MiniScalaApp.class separately
$ scalac /myProject/src/main/scala/MiniScalaApp.scala
$ scala MiniScalaApp
Question: What is the reason the scala command treats the code differently?
scala -help explains all.
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.
so the latter case which is defining object and class, It will run the code as script.
in another way to say, what It does is exactly the same as...
scala> :paste
// Entering paste mode (ctrl-D to finish)
object MiniScalaApp {
def main(args: Array[String]) = {
println(s"Scala Version: ${scala.util.Properties.scalaPropOrElse("version.number", "unknown")}")
println(new Dinosaur("Tyrannotitan", 4900))
println(new Dinosaur("Animantarx ", 300))
}
}
class Dinosaur (name:String, weightKG: Int) {
override def toString = f"$name, Weight: $weightKG kg"
}
// Exiting paste mode, now interpreting.
defined object MiniScalaApp
defined class Dinosaur
only defining.so you need to call it explicitly.
MiniScalaApp.main(Array())
In addition to that, object Foo extends App can't be used if the file have only one top-lebel object.def mainis required.
Seems like you need to invoke the main method explicitly if there is more than 1 top-level class/object:
object MiniScalaApp {
def main(args: Array[String]) = {
println(s"Scala Version: ${scala.util.Properties.scalaPropOrElse("version.number", "unknown")}")
println(new Dinosaur("Tyrannotitan", 4900))
println(new Dinosaur("Animantarx ", 300))
}
}
class Dinosaur (name:String, weightKG: Int) {
override def toString = f"$name, Weight: $weightKG kg"
}
MiniScalaApp.main(args);
See here: Main method is not called in Scala script

Why args are compulsory for main

If I use like below considering I don't need to take arguments, it doesn't detect for Scala in eclipse.
object HelloWorld {
def main(): Unit = {
println("Hello Scala!!!")
}
}
It works fine with args: Array[String]
object HelloWorld {
def main(args: Array[String]): Unit = {
println("Hello Scala!!!")
}
}
Well it's simply a convention on the JVM. You won't be able to invoke your object as entry point when running your program. For example, in Scala.js you have main() without arguments.
If you don't need the arguments you can mixin the App trait:
object HelloWorld extends App {
println("Hello Scala!!!")
}