Professional Scala
上QQ阅读APP看书,第一时间看更新

Chapter 1. Setting up the Development Environment

Before we start writing the various programs in this book, let's talk a little about the Scala language itself. Why is it necessary, and what has made Scala unique? What are the most important aspects of the language?

Scala was created in 2001 in EPFL (École Polytechnique Fédérale de Lausanne), by Martin Odersky. This is the same lab where Pascal language (widely used up to the end of the 1990s) was created.

Scala is an abbreviation for 'Scalable Language'—a language which can be scaled, that is, it allows you to write complex systems with gigantic amounts of functionality. As specified on Scala's home page: " Scala combines object-oriented and functional programming in one concise, high-level language."

Note

You can visit Scala's official home page here: https://www.scala-lang.org/

By the end of this chapter, you will be able to:

  • Recognize the structure of a Scala project
  • Identify the use of Scala's sbt tool (interactive build tool) for building and running your project
  • Identify how to use the IDE
  • Implement interactions with a simple chatbot

Scala is built on top of the JVM platform (the Scala program is compiled to use JVM bytecode).

Now, the language is used as one of the most preferred platforms in many areas, such as high-load soft-realtime applications, ad servers for data science toolkits.

Some characteristics of Scala are as follows:

  • An advanced type system, which makes Scala superior (but at the same time, more complex) compared to most other industrial programming languages.
  • Static typing, which allows you to write code in a safe way when errors are checked during compilation.

In this chapter, we will learn the basics of Scala, such as what the simple Scala program looks like and what a typical developer flow is. A significant part of development is interaction with tools—build tools, dependency extractors, IDEs, and so on, which form the tool ecosystem with the language. We will build a simple program using mainstream tools.

Simple Program

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:

package com.packt.courseware
import scala.io.StdIn
object Chatbot1
{
   def main(args: Array[String]):Unit =  {
     // do something
   }
}

Definitions: Packages, Imports, and Objects

If you look at the preceding code, the first line is a package name. In our case, this is com.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 at import statements.

Object Definition

Here, we define the object Chatbot1.

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.

The main Method

Finally, the main method is an entry point for our program. It must accept an array of strings (command-line arguments) and return a unit.

Historically, the main 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() = { … } }

Inside main

The main method is an essential part of any Scala program. The execution of a program first starts from the main method.

Let's look inside the main 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 name name, which keeps the user's input from stdin. Scala is a statically typed language, and so the value is of type String.

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 of s, all occurrences of expressions inside ${} brackets in strings are replaced with values of these expressions, casted to strings. For simple identifiers, we can omit {} brackets, for example, in a string interpolation of s"x=$y", the value of y will be substituted instead with $y.

var timeToBye is a mutable variable with a Boolean 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 answer interesting to any message, except bye.

The result of the case statement is assigned to timeToBye, and is checked in the while 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 inside while. The resulting code is smaller and better to read, but adding new functionality becomes harder. Yet there is one possibility—use the recursive function instead of the loop language construction.

Now let's add some functionality to our chatbot: when the user asks for the time, the chatbot 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 the now method of java.time.LocalTime.

The code used to display this will be println("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.courseware

import scala.io.StdIn

object 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
       }
}

}