In this section, we will be covering the structure of a basic Scala program. We will be covering definitions such as packages, imports, and objects. We will also be looking into the main method of a Scala program.
Let's create the simplest possible program in Scala. We will implement a program which will print "Hello World" on the screen. The structure of this program is defined as follows:
Definitions: Packages, Imports, and Objects
If you look at the preceding code, the first line is a package name. In our case, this iscom.packt.courseware
.
All compilation units are organized into packages. Packages can be nested, forming hierarchical namespaces for code objects.
When a compilation unit has no package declaration, it belongs to a so-called 'default
' package. Modules from a default package can't be imported from another package.
Usually, the source directory in a Scala project is organized in the same way as packages. This is not mandatory, but becomes a rule of thumb. Some tools (such as IDEs) use these conventions for default project settings.
Now we will look atimport
statements.
Here, we define the objectChatbot1.
If you are familiar with the traditional classes, since they are implemented in Java, you can look at the object of a class with one default instance, that is, an object is an implementation of the singleton pattern: on the JVM level, the object definition creates a class and one predefined instance of this class.
Finally, themain
method is an entry point for our program. It must accept an array of strings (command-line arguments) and return a unit.
Historically, themain
method name is used in Scala. This is because the Java language is following the same tradition, which takes the name of an entry method from C, which take this from BCPL.
The method is defined as follows:
package com.packt.couserware object X { def f() = { … } }
Themain
method is an essential part of any Scala program. The execution of a program first starts from themain
method.
Let's look inside themain
method:
def main(args: Array[String]): Unit = {val name = StdIn.readLine("Hi! What is your name?")println(s" $name, tell me something interesting, say 'bye' to end the talk")var timeToBye = false while (!timeToBye)timeToBye = StdIn.readLine(">") match {case "bye" => println("ok, bye") truecase _ => println("interesting...")false}}
Here, we define an immutable value with the namename
, which keeps the user's input fromstdin
. Scala is a statically typed language, and so the value is of typeString
.
As we can see, the type of the value is not explicitly written, but automatically inferred from its context.
At the next line, the value is printed using the "string interpolation" operator: In a string with a prefix ofs
, all occurrences of expressions inside${}
brackets in strings are replaced with values of these expressions, casted to strings. For simple identifiers, we canomit {}
brackets, for example, in a string interpolation ofs"x=$y"
, the value of y will be substituted instead with$y
.
var timeToBye
is a mutable variable with aBoolean
type. Unlike values, mutable variables can be assigned more than once.
Looking forward at the loop, we can see that the program is trying to be a good listener and answerinteresting
to any message, exceptbye
.
The result of the case statement is assigned totimeToBye
, and is checked in thewhile
loop condition
Scala, as a multiparadigm language, has both mutable and immutable variables. For nearly any task, we can choose more than one way of implementing this.
If guidelines exist, where should we use mutable variables and where should we use immutable variables?
Generally, reasoning about immutable variables is simpler. The usual heuristic is to use immutable values as much as possible, leaving mutable variables for performance-critical sections and state-check language constructs (such as while loops).
In our small example, we can eliminate the mutable flag by putting an expression for the loop exit condition insidewhile
. The resulting code is smaller and better to read, but adding new functionality becomes harder. Yet there is one possibility—use therecursive
function instead of the loop language construction.
Now let's add some functionality to ourchatbot
: when the user asks for thetime
, thechatbot
should report the current time.
To do this, we must retrieve the current time using the Java API and display the output of the time using string interpolators.
For example, use thenow
method ofjava.time.LocalTime.
The code used to display this will beprintln("time is ${java.time.LocalTime.now()}").
The following is the code for this functionality, but we will actually implement this after setting up the working environment we will be playing with:
package com.packt.coursewarepackage com.packt.coursewareimport scala.io.StdInobject Chatbot1 { def main(args: Array[String]): Unit = { val name = StdIn.readLine("Hi! What is your name?") println(s" $name, tell me something interesting, say 'bye' to end the talk") var timeToBye = false while (!timeToBye) timeToBye = StdIn.readLine(">") match { case "bye" => println("ok, bye") true case "time" => println(s"time is ${java.time.LocalTime.now()}") true case _ => println("interesting...") false }}}