Scala: Introductory Study Notes

I usually write notes when I am studying or learning new skills, when I was in University my classmates copied my notes to help them with their learning. That is why I am sharing my notes maybe it will help you.

Scala Basics

Scala “scalable language” runs on the Java VM and interoperates with all Java libraries. You can use Scala for writing scripts or for building large systems and frameworks. Scala is a blend of object orient and functional programming concepts. Scala’s functional programming constructs make it easy to build logic quickly from simple parts while its object-oriented constructs make it easy to structure large system and adapt them to new requirements.

Functional programming is guided by two main ideas:

  1. Functions are first class values. This means a function is a value same as integer or string. A function can passed as an argument to another function, returned as a result from a function.
  2. Operations of should map input values to output values rather than change data in place. This means methods should not have side effects. All data types and objects should be immutable.

Setting Up Scala Development Environment


Figure 1: Where to download scala

Best way to learn is by writing some code. In this section, we will go through a quick tutorial of Scala basics. To run the code samples, you should have standard Scala installation. You can get it from http://www.scala-lang.org. You can also use a Scala plug-in for Eclipse, IntelliJ or NetBeans.

Scala Interpreter


Figure 2: Scala Shell Interpreter

Scala comes with an interactive “shell” for writing Scala expressions and programs. The interpreter will evaluate expression you type and print the resulting value.

scala> 567*8+20

res0: Int = 4556

Scala Variables

Scala has two kinds of variables:

  1. val: is similar to final variable in Java or readonly in C#. once initialized it can never be reassigned.

scala> val str = “This is a book about Scala”

str: String = This is a book about Scala

scala> str = “change this string”

<console>:12: error: reassignment to val

str = “change this string”

  1. var: is similar to a non-final or non readonly variable in Java and C# respectively.

scala> var m = “This is a book about Scala”

m: String = This is a book about Scala

scala> m = “Change this string”

m: String = Change this string

Notice that in both examples, I did not define the type. Scala’s ability to infer types makes the code less cluttered with unnecessary explicit type annotations. Though an explicit type annotation can both ensure the Scala compiler infer the type you intend as well as serve as a useful documentation for the readers of the code. In Scala, you specify a variable type after is name separated by a colon.

scala> val s:String = “Hello Scala Book”

s: String = Hello Scala Book

Scala Functions

scala> def max(x:Int, y: Int): Int = {

| if(x > y) x

| else y

| }

max: (x: Int, y: Int)Int

scala> max(99,767)

res2: Int = 767

Functions definitions starts with “def”, followed by the function’s name, followed by comma-separated list of parameters in parentheses. A type annotation must follow each parameter, because Scala does not infer function parameter types. After the close parenthesis another type annotation that defines the result type of the function. You can leave the result type and Scala will infer it.

while and if constructs

var i = 0

i: Int = 0

scala> while(i < 20){

| if(i >0) println(i)

| i += 1

| }

1

2


19

While (condition) statement

The while will execute the statement or block of statements (complex statement) contained within “{}” as long as the condition is true.

If(condition) statement1 else statement2

If will execute statement1 if the condition is true. If there is an else then statement2 will get executed if the condition is false.

Arrays

scala> val big = new java.math.BigInteger(“3728”)

big: java.math.BigInteger = 3728

scala> val g = new Array[String](5)

g: Array[String] = Array(null, null, null, null, null)

scala> g(0) = “Hi”

scala> g(1) = ” ”

scala> g(2) = ” Scala”

scala> g(3) = ” Says Functional”

scala> g(4) = ” is the way to go”

You instantiate objects using the “new” keyword. You can configure the object instance when you create it. For example as shown in the code above val big with instantiated with BigInteger with value of 3728. And g was created as an array of type string with 5 elements.

Since functions are first class constructs in Scala, you can pass the function literal that takes parameter to another function. If the function literal takes a single parameter, you need not name specify the argument.

scala> g.foreach(print)

Hi Scala Says Functional is the way to go

apply & update methods

In Scala, when you apply parentheses surrounding one or more values to a variable, Scala will transform the code into an invocation of a method named apply on that variable. So g(0) is transformed to g.apply(0). Any application of an object to some arguments in parentheses will be transformed to an apply method call. This will compile only if the type of the object defines an apply method. When an assignment is made to a variable to which parentheses and one or more arguments have been applies Scala will transform that into an invocation of an update method that takes the arguments in parentheses. So g(0) = “hello” will be transformed into g.update(0,”Hello”)

Lists

Scala array is a mutable sequence of objects that all share the same type. And Array[String] contains only string. Although you can’t change the length on an array after is instantiated. You can change its elements values. For an immutable sequence of objects that share the same type you can use Scala’s List class. List[String] can contain only strings.

scala> val a = List(1,2,3)

a: List[Int] = List(1, 2, 3)

scala> val b = List(7,8,3)

b: List[Int] = List(7, 8, 3)

scala> val ab = a ::: b

ab: List[Int] = List(1, 2, 3, 7, 8, 3)

scala> val s = 1::b

s: List[Int] = List(1, 7, 8, 3)

The code above establishes a new val named a initialized with a new List[Int] with values 1,2, and 3. Note that List.apply() is defined as a factory method in Scala. When you call a method on a List that might mutate the list, it will creates and returns a new list with the new value. For example the ::: method is for list concatenation.

scala> val k = 1 :: 2 :: 8 :: 9 :: Nil

k: List[Int] = List(1, 2, 8, 9)

Note, the method :: is method on its right operand in Scala, this issue will be discussed in more detail later.

Tuples

Tuple are a useful object contain. Tuples are immutable and contain different types of elements. Tuples are similar to C language struct construct. Though you do define the tuple structure in advance. Typically you use tuples when you need to return multiple objects from a method.

scala> val complexTuple = (78,”Rony”, “Alicante”, “Spain”)

complexTuple: (Int, String, String, String) = (78,Rony,Alicante,Spain)

scala> println(complexTuple._1)

78

scala> println(complexTuple._3)

Alicante

Once you have a tuple instantiated, you can access its elements individually with a dot, underscore, and the one-based index of the element, as shown in the example above.

Sets and Maps

Scala provides mutable and immutable alternatives for sets and maps, both use the same simple names but they are in different packages or namespaces. The default is the immutable set as shown in the listing below. The ‘+=’ operation returns a new set that is why the operation succeeds with var and fails with val.

scala> var set1 = Set(“Alicante”,”Granada”)

set1: scala.collection.immutable.Set[String] = Set(Alicante, Granada)

scala> var set2 = set1

set2: scala.collection.immutable.Set[String] = Set(Alicante, Granada)

scala> set2 += “Barcelona”

scala> set1

res20: scala.collection.immutable.Set[String] = Set(Alicante, Granada)

scala> set2

res21: scala.collection.immutable.Set[String] = Set(Alicante, Granada, Barceolona)

scala> val set3 = set1

set3: scala.collection.immutable.Set[String] = Set(Alicante, Granada)

scala> set3 += “Barcelona”

<console>:13: error: value += is not a member of scala.collection.immutable.Set[String]

Expression does not convert to assignment because receiver is not assignable.

set3 += “Barcelona”

to use the mutable version you import the scala.collection.mutable package as shown in the listing below

scala> import scala.collection.mutable

import scala.collection.mutable

scala> val mutableset = mutable.Set(“Alicante”,”Granada”)

mutableset: scala.collection.mutable.Set[String] = Set(Alicante, Granada)

scala> mutableset += “Barceolona”

res24: mutableset.type = Set(Alicante, Barceolona, Granada)

Now the ‘+=’ operator works with ‘val’ as the set is modified. The listing below shows similar operations for Map. To create a mutable Map use scala.collection.mutable package Map class implementation. The default Map uses the immutable implementation.

scala> val areaCode = mutable.Map[Int,String]()

areaCode: scala.collection.mutable.Map[Int,String] = Map()

scala> areaCode += (416-> “Toronto”)

res25: areaCode.type = Map(416 -> Toronto)

scala> areaCode += (905-> “GTA”)

res26: areaCode.type = Map(905 -> GTA, 416 -> Toronto)

scala> areaCode += (613-> “Calgary”)

res27: areaCode.type = Map(905 -> GTA, 613 -> Calgary, 416 -> Toronto)

scala> val stars = Map( 1->”*”,2->”**”,3->”***”,4->”****”,5->”*****”)

stars: scala.collection.immutable.Map[Int,String] = Map(5 -> *****, 1 -> *, 2 -> **, 3 -> ***, 4 -> ****)

scala> println(stars(3))

***

Semicolon Inference

In Scala, a semicolon at the end of a statement is usually optional. You can type one if you want but you do not have to if the statement appears by itself on a single line. On the other hand, a semicolon is required if you write multiple statements on a single line:

scala> val s = “Moustafa”; println(s)

scala> if (x <2)

| println(“too small”) else

| println(“Ok”)

Control Structures

Scala has the following control structures:

  1. if: if works like in Java and C#, it tests a condition and then executes one of two code branches depending on whether the condition holds true.

scala> var args:Array[String] = Array()

args: Array[String] = Array()

scala> val fileName = if(!args.isEmpty) args(0) else “default.txt”

fileName: String = default.txt

  1. while: Just like in C# and Java while has a conditions and a body. The body is executed over and over again as long as the condition holds true.

scala> var a = 20

a: Int = 20

scala> var b = 30 ;

b: Int = 30

scala> while (a != 0) { val temp = a

| a = b% a

| b = temp

| }

scala> b

res1: Int = 10

another form of the while loop is the do-while where the code block is executed at least once and keeps on executing as long as the while condition is true

do {

| line = readLine()

| println(” Read: “+ line)

| } while (line !=””)

  1. for: Scala’s for expression lets you combine a few simple ingredients in different ways to express a wide variety of iterations.
    1. Iteration through collections

val filesHere = (new java.io.File(“.”)).listFiles

for(file <- filesHere) println(file)

for ( i<- 1 to 4) prinrln(“Iterntion “+i)

  1. Filtering

val filesHere = (new java.io.File(“.”)).listFiles

for(file <- filesHere

if file.isFile

if file.getName.endsWith(“.scala”)) println(file)

  1. Nested Iteration

def fileLines(file: java.io.File) =
scala.io.Source.fromFile(file).getLines().toList

    def grep(pattern: String) =
								for (
    file <- filesHere
											if file.getName.endsWith(".scala");
    line <- fileLines(file)
															if line.trim.matches(pattern) 
  ) println(file + ": " + line.trim)
  1. Mid-stream variable bindings same as example above

  • Producing a new collection

 

val filesHere = (new java.io.File(“.”)).listFiles

val forLineLengths =

for {
file <- filesHere

if file.getName.endsWith(“.scala”)
line <- fileLines(file)
trimmed = line.trim

if trimmed.matches(“.*for.*”)
} yield trimmed.length

To generate a new value for each iteration in a for expression prefix the for expression body by the keyword ‘yield’. As in the example above each time the body of the for expression executes it produces one value in this case the length of the trimmed line.

  1. Try: this issued for handling exceptions.

def throws1 {

throw new IllegalArgumentException
}

def throws3 {

import java.io.FileReader

import java.io.FileNotFoundException

import java.io.IOException

try {

val f = new FileReader(“input.txt”)

// Use and close file

println(“f [” + f + “]”)
} catch {

case ex: FileNotFoundException => // Handle missing file

println(“ex [” + ex + “]”)

case ex: IOException => // Handle other I/O error

println(“ex [” + ex + “]”)
}

finally {
file.close() // Be sure to close the file
}


}

  1. Match: Scala match expression is similar to C# and Java switch statement. With default case si specified with an underscore (_) and there is no flow from case to case so no need for a break statement
def match2(args: Array[String]) {
								val firstArg = if (!args.isEmpty) args(0) else ""
																	
																	val friend =
    firstArg match {
																		case "salt" => "pepper"
																						case "chips" => "salsa"
																								case "eggs" => "bacon"
																										case _ => "huh?"
																											}           
																												
																												println(friend)
}
  1. function calls.

Almost all of Scala’s control structures result in some value even try expressions

def urlFor(path: String) =
								try {
										new URL(path)
  } catch {
														case e: MalformedURLException =>
																new URL("http://www.scala-lang.org")
  }

Scala does not have break and continue because they do not mesh well with functional literals.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

Website Powered by WordPress.com.

%d bloggers like this: