Data types
Boolean true or false
Byte 8 bit signed value
Short 16 bit signed value
Char 16 bit unsigned Unicode character
Int 32 bit signed value
Long 64 bit signed value
Float 32 bit IEEE 754 single-precision float
Double 64 bit IEEE 754 double-precision float
String A sequence of characters
Unit Corresponds to no value
Null null or empty references
Nothing subtype of every other type; includes no ...
Any The supertype of any type; any object is of ..
AnyRef The supertype of any reference type
More on datatype: https://www.tutorialspoint.com/scala/scala_data_types.htm
Variables
// mutable variable: variable value can be changed
var myVar : String = "Foo"
// imutable variable: variable value cannot be changed
val myVar : Int = 10
// Note: scala will detect the data types by the initial values.
val x = {val a: Int = 200; val b: Int = 300; a+b}
// this value is not assigned until x is used (you are only using memory in demand)
lazy val x = 500
String
String interpolation
val name = "mark"
val age = 18
println(name + " is" + age + " year old.")
println(s"$name is $age years old.")
println(f"$name%s is $age%d years old.") //typesafe: %s specifies string type and %d specifies double type
// mark is 18 years old.
println(raw"Hello \nworld.")
// Hello \nworld.
println(s"Hello \nworld.")
// Hello
// world.
Methods for Strings
val str1: String = "Hello world";
val str2: String = " Max";
// calculate length
println(str1.length()) // returns 11
// concatenate
println(str1.concat(str2)) // returns "Hellow world Max"
println(str1 + str2)
// formating
val num1 = 75;
val num2 = 100.25;
val result = printf("(%d -- %f -- %s)", num1, num2, str1);
println(result);
println("(%d -- %f -- %s)".format(num1, num2, str1));
Arrays
An array is a data structure which can store fixed-sized sequential elements of same data type.
val myarray: Array[Int] = new Array[Int](4);
// index starts from 0 in Scala
myarray(0) = 20;
myarray(1) = 50;
myarray(2) = 10;
myarray(3) = 10;
// println(myarray) // won't work
for(x <- myarray){
println(x);
}
// Default values of an array
val myarray2 = new Array[Int](5); // default value is 0
val myarray2 = new Array[String](5); // default value is null
val myarray2 = new Array[Double](5); // default value is 0.0
val myarray2 = new Array[Boolean](5); // default value is false
// concatenate
import Array._
val myarray3 = Array(1, 2, 3, 5, 8);
println(myarray3.length)
val result = concat(myarray3, myarray3);
for(x <- result){
println(x)
}
Collections
Lists
Lists are immutable and represent the link lists whereas arrays are mutable and flat.
val mylist: List[Int] = List(1, 2, 5, 8);
val names: List[String] = List("Max", "Tom", "John")
println(mylist)
println(names)
println(mylist(0))
//mylist(0) = 5 // cannot change the value of a list
println(0 :: mylist) // prepend 0 but won't change mylist
println(Nil) // create a empty list
println(1 :: 5 :: 9 :: Nil) // create a list
println(List.fill(5)(2)) // returns List(2, 2, 2, 2, 2)
println(mylist.head)
println(names.tail) // print everything except for the first element
println(names.isEmpty)
println(mylist.reverse)
println(mylist.max)
// iterate over each element and run the given function
mylist.foreach( println )
var sum: Int = 0;
mylist.foreach( sum += _)
println(sum) // sum up all the elements
Sets
A set is a collection of different elements of CM data types. So a set cannot have duplicated values inside them.
val myset: Set[Int] = Set(1, 2, 2, 5)
println(myset) // returns Set(1, 2, 5)
By default, set is immutable in Scala. If we need to declare a mutable set, we can use scala.collection.mutable.Set instead.
val myset2 = scala.collection.mutable.Set(1, 3, 5)
println(myset2)
To add a value into the set
println(myset + 10)
println(myset) // myset is not changed because it's immutable
Set is not ordered, which means the new element is assigned to a random location and you cannot index an element.
println(myset(8)) // check if 8 exists in myset or not
Other useful functions in set:
println(myset.head)
println(myset.tail)
println(myset.isEmpty)
// concatenate two sets
println(myset ++ myset2)
println(myset.++(myset2))
// find intersection of two sets
println(myset.&(myset2))
println(myset.intersect(myset2))
// find min & max
println(myset.min)
println(myset.max)
// for loop
myset.foreach(println)
for(x <- myset){ println(x) }
Maps
A map is a collection of key-value pairs, for example 801-max, 802-tom, 804-july.
val mymap : Map[Int, String] = Map(801 -> "max", 802 -> "tom", 804 -> "july");
println(mymap)
println(mymap(802))
Duplication of keys is not possible in a map.
val mymap : Map[Int, String] = Map(801 -> "max", 802 -> "tom", 804 -> "july", 804 -> "jully");
println(mymap); // it takes the last entry of 804
println(mymap.keys) // returns a set
println(mymap.values)
println(mymap.isEmpty)
println(mymap.contains(801000)) // check if a key (or exception case) is valid/exist in the map
//for loop
mymap.keys.foreach{ key =>
println("key " + key);
println("value " + mymap(key));
}
//concatenate
val mymap2 : Map[Int, String] = Map( 805 -> "lua");
println(mymap ++ mymap2);
Tuples
A tuple is a class that can contain different kinds of elements, unlike array. A tuple is immutable in scala. You cannot change a tuple once it’s declared. A tuple can contain 22 elements at most.
val mytuple = (1, 2, "hello", true);
println(mytuple);
val mytuple2 = new Tuple3(1, 2, "hello"); // have to indicate the number of elements in a tuple right after the "Tuple" keyword; maximum number is 22.
println(mytuple._3) // returns the third element
val mytuple3 = new Tuple3(1, "hello", (2,3))
println(mytuple3._3._2); // print 3
//for loop
mytuple.productIterator.foreach{
i => println(i)
}
Options
An option is a container which can give you two values (Some or None).
val lst = List(1, 2, 3);
val map = Map(1 -> "Tom", 2 -> "Max", 3 -> "John");
println(lst.find(_ > 6)); // return None
println(lst.find(_ > 2)); // return Some(3)
println(map.get(1)); // return Some(Tom)
println(map.get(4)); // return None
// to abstract the values
println(lst.find(_ > 2).get); // return the element value 3
println(map.get(5).get); // get an exception error message
// to avoid exception error message
println(map.get(5).getOrElse("No name found."));
// to define options
val opt : Option[Int] = None;
println(opt.isEmpty); // returns true
val opt2 : Option[Int] = Some(55); // returns false
Ifelse statement
val x = 20
var res = ""
if(x == 20){
res = "x==20"
} else {
res = "x!=20"
}
println(res)
val res2 = if(x == 20) "x==20" else "x!=20"
println(res2)
println(if(x == 20) "x==20" else "x!=20")
Use && for and and || for or.
Match expressions
val age: Int = 18
age match {
case 18 => println("age 18")
case 20 => println("age 20")
case _ => println("default") // catch default/unmatched case
}
// use as expression
val result = age match {
case 18 => "age 18"
case 20 => "age 20"
case _ => "default" // catch default/unmatched case
}
println("result = " + result)
// mutiple expressions
val i =8;
i match {
case 1|3|5|7|9 => println("odd")
case 2|4|6|8|10 => println("even")
}
Loops
while loop
check the condition before executing
var x = 0
while(x < 10){
println("x = " + x)
x += 1 // x = x + 1
}
do-while loop
execute at least once regardless of the condition
var y = 0
do {
println("y = " + y)
y += 1
} while (y < 0);
for loop
for ( i <- 1 to 5){
println("i using to " + i)
}
// identical
for ( i <- 1 until 6){
println("i using to " + i)
}
for ( i <- 1 to 5; j <- 1 to 3){
println("i,j using to " + i + "," + j)
}
val lst = List(1, 5, 3, 2, 8)
for( i <- lst; if i < 3){
println("i using to " + i)
}
// Use for loop as an expression
val result = for { i <- lst; if i < 3 } yield {
i * i
}
println("result = " + result) // return a List
Map, flatten, and filter
Map method
val lst = List(1, 2, 3, 5, 7, 9, 10);
val mymap = Map(1 -> "Tom", 2 -> "Max", 3 -> "John");
// double every element in lst
println(lst.map(x => x*2))
println(lst.map(_ *2))
println(mymap.mapValues(x => "hi " + x));
// apply toUpper to every element in the string "hello"
println("hello".map(_.toUpper))
Flatten method
// flatten contents of a list of lists
println(List(List(1, 2, 3), List(3, 4, 5)).flatten)
println(lst.flatMap(x => List(x, x+1)))
Filter method
// abstract even numbers
println(lst.filter(x => x%2 == 0))
Reduce, fold, and scan (left/right)
Reduce method
val lst = List(1, 2, 3, 4, 6, 7, 8);
val lst2 = List("A", "B", "C");
println(lst.reduceLeft(_ + _)) // returns sum of all elements
println(lst2.reduceLeft(_ + _)) // returns "ABC" by (AB)C
println(lst2.reduceRight(_ + _)) // returns "ABC" by A(BC)
println(lst.reduceLeft((x, y) => {println(x + ",", + y); x+y;}))
Fold method is similar to reduce method but can insert initial argument.
println(lst.foldLeft(10)(_ + _)) // return 10 + sum(lst)
Scan method takes initial value and applies it to each element in reduce method. It returns the map of intermediate results.
println(lst.scanLeft(10)(_ + _))
println(lst2.scanLeft("z")(_ + _))
Lazy evaluation
Lazy evaluation is an evaluation strategy that delays the evaluation of an expression until it’s needed. Scala supports strict evaluation by default and lazy evaluation if specified.
val e = 9; // strict evaluation
lazy val l = 9; // lazy evaluation
call-by-value v.s. call-by-name
# call-by-value, the general case
def method1(n: Int) {
println("Method 1");
println(n);
}
# call-by-name
def method2(n: => Int) { // use =>
println("Method 2");
println(n);
}
val add = (a: Int, b: Int) => {
println("Add");
a + b
}
method1(add(5, 6))
// Add
// Method 1
// 11
method2(add(5, 6))
// Method 2
// Add
// 11
Scala in IntelliJ IDEA
SBT tasks
The following tasks can be run in sbt shell:
Scala interpreter: type
console
to start and typeto quit Type
compile
to compile the source code located in the directory src/main/scalaType
test
to test the unit tests for the project located in src/test/scalaIf your project has an object with a main method (or an object extending the trait App), then you can run the code in sbt easily by typing
run
. In case sbt finds multiple main methods, it will ask you which one you’d like to execute.
Unit test
package example
import java.util.NoSuchElementException
import org.scalatest.FunSuite
import org.junit.runner.RunWith
import org.scalatest.junit.JUnitRunner
/**
* This class implements a ScalaTest test suite for the methods in object
* `Lists` that need to be implemented as part of this assignment. A test
* suite is simply a collection of individual tests for some specific
* component of a program.
*
* A test suite is created by defining a class which extends the type
* `org.scalatest.FunSuite`. When running ScalaTest, it will automatically
* find this class and execute all of its tests.
*
* Adding the `@RunWith` annotation enables the test suite to be executed
* inside eclipse using the built-in JUnit test runner.
*
* You have two options for running this test suite:
*
* - Start the sbt console and run the "test" command
* - Right-click this file in eclipse and chose "Run As" - "JUnit Test"
*/
@RunWith(classOf[JUnitRunner])
class ListsSuite extends FunSuite {
// We fist import all members of the `List` object.
import Lists._
test("sum of a few numbers") {
assert(sum(List(1,2,0)) === 3)
assert(sum(List(-2, -1, -5)) === -8)
assert(sum(List(0, 0, 0)) === 0)
assert(sum(List()) === 0)
}
test("max of a few numbers") {
assert(max(List(3, 7, 2)) === 7)
assert(max(List(-3, -7, -2)) === -2)
assert(max(List(2, 2, 2)) === 2)
assert(max(List(-3, 0, 3, -5)) === 3)
intercept[NoSuchElementException]{ max(List()) }
}
}
Comment code
Comment one line
Comment multiple lines