Jun 22, 2018 ▪ 21 min read (~3 pages) Computer Science Updated on Jan 03, 2023

A Scala Primer and Cheat Sheet

1. Introduction

Scala program structure (build and run with $ scalac <filename>.scala && scala <filename>).

object Main {
    // do something

    def main(args: Array[String]) {
        // do something
    }
}

Handling exceptions.

try {
    // do something
}
catch {
    case a: ArithmeticException => println("This is an arithmetic error: " + a)
    case b: Throwable => println("Error: " + b)
}
finally {
    // do something
}

Build and run in Sublime Text (build system).

{
    "cmd": ["scala", "$file"],
    "path": "$PATH:/usr/local/bin",
    "file_regex": "^(.+):(\\d+): .+: (.+)",
    "selector": "source.scala"
}

2. Arithmetic Operators

Basic arithmetic operators.

10 + 20
// 30
20 - 10
// 10
10 * 20
// 200
20 / 10
// 2

Automatic floating point conversion.

10.0 + (10 + 20)
// 40.0
20.0 - (10 + 10)
// 0.0
10.0 * (10 * 2)
// 200.0

Be aware of this common division error.

30 / 20
// 1
30.0 / 20.0
// 1.5

Modulo (remainder).

12.5 % 10.0
// 2.5
10.0 % 20.0
// 10.0

3. Variables

Use val keyword to make data immutable.

val x: Int = 6
val y: String = "String"
val z: Double = 1.05
x, y, z
// (6,String,1.05)

Use getClass.getSimpleName to get type.

x.getClass.getSimpleName
// int
y.getClass.getSimpleName
// String
z.getClass.getSimpleName
// double

Use var keyword to make data mutable.

var a = x
// 6
a = a + 2
// 8

Multiple assignments.

val (x, y, z) = (6, "String", 1.05)
// (6,String,1.05)

List assignments.

val List(d, t, v) = List(230, 45, 12)
// (230,45,12)

String assignments.

val string: String = "100B"

4. Strings

4.1 Indexing

val string: String = "proton"

Use charAt and slice to index and slice string.

string.charAt(0)
// p
string.slice(0,4)
// prot

Length of string.

string.length
// 6

Index and slice using substring.

string.substring(0, string.length)
// proton
string.substring(string.length - 4, string.length)
// oton

4.2 Operations

String operations.

"kilo" ++ "meter"
// kilometer
"A" * 4
// AAAA
val string: String = "proton neutron"
string.capitalize
// Proton neutron
string.toUpperCase
// PROTON NEUTRON
string.toLowerCase
// proton neutron

Counting and finding letters in text

string.count(_ == 'p')
// 1
string.indexOf("t")
// 3

Removing whitespace from string

val string: String = "    some text    "
string.trim
// some text

5. Data structures

5.1 Lists

Lists are immutable.

val list_one: List[String] = List("Alpha", "Beta")
// List(Alpha, Beta)
val list_two: List[Any] = List(200, -2, List(1.0, 0.0))
// List(200, -2, List(1.0, 0.0))
val list_range: List[Int] = List.range(1, 10)
// List(1, 2, 3, 4, 5, 6, 7, 8, 9)

Concatenate lists.

val list_all = list_one ++ list_two
// List(Alpha, Beta, 200, -2, List(1.0, 0.0))

Create new list by adding item to an existing list.

val list_one_new = "Gamma"  :: list_one
// List(Gamma, Alpha, Beta)

List operations.

list_one_new.length
// 3
list_one_new.sorted
// List(Alpha, Beta, Gamma)
list_two.head
// 200
list_two.last
// List(1.0, 0.0)
list_range.filter(_ > 5)
// List(6, 7, 8, 9)
List(1, 2, 3, 4).sum
// 10
List(1, 2, 3, 4).min
// 1
List(1, 2, 3, 4).max
// 4

Create list from a string

val list_char: List[Char] = ("100B").toList
// List(1, 0, 0, B)

5.2 Tuples

Tuples are immutable.

val tuple_one = (1.0, "String", 4)
// (1.0,String,4)
val tuple_two = ("Alpha", "Bravo", (1, 0))
// (Alpha,Bravo,(1,0))
tuple_one._2
// String
tuple_two._3._2
// 0

Assign values in tuple to variables

val (first, second, third) = ("Alpha", "Beta", "Gamma")
first
// Alpha
second
// Beta
third
// Gamma

5.3 Maps

Maps are key-value pairs and immutable.

val map_any = Map("Adam" -> List("[email protected]", 2445055),
                  "Bard" -> "[email protected]" )
map_any("Adam")
// List([email protected], 2445055)
map_any.contains("Bard")
// true
map_any.exists(_ == "Bard" -> "[email protected]")
// true

Using collection.mutable.Map for mutable maps.

val map_mutable = scala.collection.mutable.Map[String, Int]()
map_mutable += ("Alpha" -> 1, "Beta" -> 2)
// Map(Beta -> 2, Alpha -> 1)
map_mutable -= "Beta"
// Map(Alpha -> 1)
map_mutable("Alpha") = 100
// Map(Alpha -> 100)

5.4 Sets

Sets are immutable.

val set_numbers: Set[Int] = Set(1, 3, 5, 7, 9)
// Set(5, 1, 9, 7, 3)
set_numbers.contains(3)
// true
set_numbers.contains(2)
// false

Using collection.mutable.Set for mutable sets.

val set_mutable_one = scala.collection.mutable.Set(1, 3, 5)
val set_mutable_two = scala.collection.mutable.Set(5, 7, 9)
set_mutable_two += 11
// Set(9, 5, 7, 11)
set_mutable_two -= 11
// Set(9, 5, 7)

Set operations (using clone to copy).

val A = set_mutable_one.clone
val B = set_mutable_two.clone
A | B
// Set(9, 1, 5, 3, 7) 		(Union)
A & B
// Set(5) 					(Intersection)
A &~ B
// Set(1, 3) 				(Difference)
A union B
// Set(9, 1, 5, 3, 7)
A intersect B
// Set(5)
A diff B
// Set(1, 3)

Subsets.

A subsetOf B
// false

6. Conditionals

6.1 If-Else

val a: Double = 1.0
val b: Double = 5.0
if (a < 1.0) {
    // do something
}
else if (a == 1.0) {
    // do something
}
else {
    // do something
}

6.2 Logical Operators

Booleans.

val T: Boolean = true
val F: Boolean = false
T || F
// true
T && (T && F)
// false
!T
// false
!(!T)
// true

Numbers.

1 == 2
// false
1 != 2
// true

7. Loops

7.1 For

val numbers: List[Int] = List(1, 2, 3, 4)
// List(1, 2, 3, 4)
for (number <- numbers) {
    // do something
}

Nested for loops.

for (i <- List.range(1, 5)) {
    for (j <- List.range(1, 5)) {
        // do something
    }
}

Using for-loops and maps

val map: Map[String, Int] = Map("Alpha" -> 1, "Beta" -> 2)
for ((key, value) <- map) {
    println(key, value)
// (Alpha,1) (Beta,2)
}

7.2 While

var a = 0
var b = 5
while (a < b) {
    // do something
    a += 1
}
println(a)
// 5

8. Functions

Functions are defined with def keyword.

def fun(): Boolean = {
    // do something
    return true
}

Addition operator as function.

def add(a:Int, b:Int): Int = {
    return a + b
}
add(2, 3)
// 5

Default arguments.

def add(a:Int, b:Int = 3): Int = {
    return a + b
}
add(2)
// 5

Multiple return values.

def add(a:Int, b:Int): (Int, Int, Int) = {
    var result = a + b
    return (a, b, result)
}
val (a, b, result) = add(2, 3)
// (2,3,5)

Documentation (scaladoc).

/** Documentation for fun.
 *
 *  @param arg an argument
 */
def fun(arg:Any) = {
    // do something
}

9. Classes

Classes are defined with class keyword.

class Money(val a:Int, val c:String) {
    var amount: Int = a
    var currency: String = c
    
    override def toString = amount.toString ++ " " ++ currency
}

Create new instance of class.

val money = new Money(220, "EUR")
money.amount, money.currency
// (220,EUR)

Print use toString.

println(money)
// 220 EUR

Subclasses.

class VirtualMoney(override val a:Int, override val c:String, val d:String) extends Money(a, c) {
    var date: String = d
    
    override def toString = amount.toString ++ " " ++ currency ++ " (use before " ++ date ++ ")"
}
val virtual_money = new VirtualMoney(20, "DIS", "2018-12-31")
println(virtual_money)
// 20 DIS (use before 2018-12-31)

10. Files

Use io.Source to read and write to files.

import scala.io.Source

Reading from files.

val file = Source.fromFile("path/to/file")
for (line <- file.getLines) {
    // do something
}

Use close to close file.

file.close

Write to text-file (using Java io).

import java.io._
val file = new File("path/to/file.txt")
val buffer = new BufferedWriter(new FileWriter(file))

buffer.write("Text.")
buffer.close

11. Modules

11.1 Calendar

import java.util.Calendar
import java.text.SimpleDateFormat
val now = Calendar.getInstance.getTime
// Sun Jun 17 19:18:49 CEST 2018

Date formats.

val year = new SimpleDateFormat("yyyy")
val month = new SimpleDateFormat("M")
val day = new SimpleDateFormat("d")
val hour = new SimpleDateFormat("H")
val minute = new SimpleDateFormat("m")
year.format(now)
// 2018
month.format(now)
// 6
day.format(now)
// 17
hour.format(now)
// 19
minute.format(now)
// 18

11.2 Math

import scala.math._
scala.math.Pi
// 3.141592653589793
scala.math.E
// 2.718281828459045

Mathematical operations.

scala.math.pow(2, 3)
// 8.0
scala.math.floor(2.945)
// 2.0
scala.math.exp(1)
// 2.718281828459045
scala.math.sqrt(16)
// 4.0
scala.math.abs(-20)
// 20
scala.math.sin(4 * math.Pi / 180)
// 0.0697564737441253

Rounding values.

scala.math.round(2.945)
// 3
scala.math.round(2.495)
// 2
scala.math.rint(2.945 * 100) / 100
// 2.94