Scala Introduction

Scala - a blend of different concepts

  • Fusion of functional and object-oriented programming
  • Advanced language features

    • Mixin composition with traits
    • Closures
    • Pattern matching with case classes
    • Expressive language
    • Macros
  • Advanced static type system

    • Unified type system
    • Type inference (leads to more concise code)
    • Path-dependent types
    • Better documentation

Scala lets you program in a pleasantly concise style and at the same time "you have the assurance that you will not outgrow the language" [s. PIS p 42-43]. Because Scala was designed to be easily extended and adapted to the needs of the people programming it, it gives you convenience and flexibility at the same time. It allows you to implement your own abstractions that address new domains, yet still feel like native language support, i.e. you can write your own types, control constructs or even a whole domain specific language and their use would 'feel' just like using built-in types or language features.

Scala blends object-orientated and functional programming. In Scala really everything is an object, from primitives to function values, and every operation is a method call. For example, when you say 1+1 you are invoking the method + defined in the class Int on 1 - just as if you had written 1.+(1).

Scala is also a functional language, i.e. it supports the following two main ideas:

The first means that you can pass functions as arguments to other functions, return them as results and bind them to variables. It is also possible to define a function in another function or to use functions anonymously. These features are convenient means for abstracting over operations and creating new control structures. They provide great expressiveness, which leads to legible and succinct programs.

The second idea can also be stated in the way, that methods should not have any side effects. Functional programming usually encourages the use of immutable data structures and referentially transparent methods (for any given input the method call could be replaced by its result without affecting the programs semantics), but Scala gives you a choice here: When you want to, you can write in an imperative style with mutable data and side effects - i.e. writing statements rather than expressions - or you can choose to take the functional route and avoid imperative constructs.

[s. Programming in Scala 49ff]

Suereth (Scala in Depth) gives a quick overview over attributes commonly associated with the two different paradigms in Scala in Depth :

Object-orientated programming Functional programming
Composition of objects Compositions of functions
Encapsulated stateful interaction Deferred side effects [Immutable objects!]
Iterative algorithms Recursive algorithms
Imperative flow Lazy evaluation
N/A Pattern matching

He illustrates this with two code examples that achieve the same results (a full cat) with different means:

class Bird
class Cat{
	def catch(b:Bird): Unit = ...
	def eat():Unit = ...
}
val cat = new Cat
val bird = new Bird
cat.catch(bird)
cat.eat
trait Cat
trait Bird
trait Catch
trait FullTummy

def catch(hunter: Cat, prey: Bird): Cat with Catch
def eat(consumer: Cat with Catch): Cat with FullTummy

val story = (catch _) andThen (eat _) // functional composition
story(new Cat, new Bird)

Literature

  • Odersky, M., Spoon, L. & Venners, B. 2011. Programming in Scala (2nd ed.).
  • Suereth, Joshua D. 2021. Scala in Depth.
  • Larman, C. 2004. Applying UML and Patterns: An Introduction to Object-Oriented Analysis and Design and Iterative Development.
  • Gamma, E., Helm, R. & Johnson, Ralph E. 1994. Design Patterns: Elements of Reusable Object-Oriented Software.
  • Meszaros, G. xUnit Test Patterns: Refactoring Test Code.
  • Martin, Robert C. 2008. Clean Code: A Handbook of Agile Software Craftsmanship.
  • Martin, Robert C. 2011. Agile Software Development - Principles, Patterns and Practices.

Additional Learning Resources

A good starting point would be the Scala documentation.

Twitter made a series of concise and succinct in-house lectures public: Scala School

There are numerous blogs, for example:

http://joelabrahamsson.com/programming/scala

http://www.codecommit.com/blog/scala/scala-for-java-refugees-part-1

http://danielwestheide.com/scala/neophytes.html (for the advanced learner)

A free eBook, if you like:

Odersky, M., Spoon, L. & Venners, B. 2008. Programming in Scala.

Or a free video tutorial that focusses on functional programming by Martin Odersky:

Functional Programming Principles in Scala

Getting a glimpse of the syntax

Getting a glimpse of the syntax

 def quicksort[T <% Ordered[T]](list: List[T]): List[T] = {
    list match {
      case Nil => Nil;
      case x :: xs =>
        val (before, after) = xs.partition({ i => i.<(x) });
        quicksort(before).++(quicksort(after).::(x));
    };
  }

[SID, p.9]

Getting a glimpse of the syntax

 def quicksort[T <% Ordered[T]](list: List[T]): List[T] = {
    list match {
      case Nil => Nil;
      case x :: xs =>
        val (before, after) = xs.partition({ i => i.<(x) });
        quicksort(before).++(quicksort(after).::(x));
    };
  }

"You may be thinking, 'Wow, Scala looks ugly.' In this case you would be right." [SID, p.10]

So let's do better...

Getting a glimpse of the syntax

def quicksort[T <% Ordered[T]](list: List[T]): List[T] = list match {
    case Nil => Nil;
    case x :: xs =>
      val (before, after) = xs partition (_ < x);
      quicksort(before) ++ (x :: quicksort(after));
  }

Note that

  • x.foo(); is the same as x foo
  • x.foo(y); is the same as x foo y
  • x.::(y); is the same as y :: x

Variables

Variables

// some values
val pi = 3.142          // implicit-type: Double
val e: Float = 2.718f   // explicit-type: Float
val g = 9.81f           // implicit-type: Float

// some variables
var r: Float = 5            // Type: Float
var cycleArea = pi * r * r  // Type: Double

var mass = 60               // Type: Int
var force = mass * g        // Type: Float


// Greatest common divisor of x and y
var x = 3
var y = 6
while (y != 0) {
  val tmp = x % y
  x = y
  y = tmp
}
val gcd = x

Value types

Scala's type-system has a separated sub-system with value-types (every type extending AnyVal). Scala supports the same types than Java (except of capitalisation):

Different to Java these types are defined as classes and operations (like +, ==, &&, ...) are defined as functions on this classes.

Variables

A variable can be declared with the keyword var:

Local variables must have a initial value.

As you can see, in Scala you don't need an explicit type-declaration if the compiler can infer the right type. But if you need a specific type or the compiler might be unable to infer the type, you can always manually declare a type:

The r-declaration is a good example where a type-declaration can be needed: the compiler would have inferred the type Int but if you strictly (for whatever reason) need or would like to have a Float-value you can declare r to be so.

If you declare a variable of some explicit type and want to initialize with a default-value, you can use the default-value _. This default-value can be used for every type and gets converted into:

Values

A value can be declared with the keyword val:

A value is a variable, that can only be assigned once.

As in the example of variables, value don't need an explicit type but can have one.

Constants

A constant in Scala can be declared with:

The difference between values and constants is, that a constant always returns the same result, whereas a value (for example a class attribute) can in some cases be overridden by a subclass.

Class attributes

A declaration of a class attribute is similar to a declaration of a local variable, value or constant:

Class attributes can be declared as variables, value or constants and can have explicit types.

Loops

While-loops

Java knows a while- and a do-while-loop. Both structures are available in Scala, too. The syntax in Java and Scala is the same:

while(condition) {
  statement
}

do {
  statement
} while(condition)

For-loops in Java (small revision)

Java knows two kinds of for-loops:

  1. a variant to use some variable that gets modified after each iteration
  2. a variant to iterate over something extending Iterable

For with some variable

The first structure isn't much more than some additional syntactic sugar to a while-loop.

for (declaration; condition; modifier) {
  statement
}

is the same as

declaration
while (condition) {
  statement
  modifier
}

For with iterable

The second variant omits some 'counter' and uses an Iterator and hence the following constructs are equivalent (except of the fact, that the variable it isn't accessible):

for (Type tmp_name : iterable) {
  statement
}
Iterator it = iterable.iterator();
while (it.hasNext()) {
  Type tmp_name = it.next();
  statement
}

For-loops in Scala

To explain for-loops in Scala, it is easier to start with the second variant. Scala uses (as usual) some other syntax but the semantic is the same:

for (tmp_name <- iterable) {
  statement
}

The temporary variable can be declared together with some explicit type (compatible with the one of the Iterable's elements) but needn't to.

Scala offers some possibility to use the Scala for-loop much like the Java for-loop with variable:
In Scala you can declare a Range of numbers with can be seen as a list-like collection containing the elements between the given limits:

scala> (0 to 5)
res0: scala.collection.immutable.Range.Inclusive = Range(0, 1, 2, 3, 4, 5)

scala> (0 until 5)
res1: scala.collection.immutable.Range = Range(0, 1, 2, 3, 4)

This Range is iterable and hence you can use the for-loop like:

for (i <- 0 to 5) {
  statement
}

which is pretty much like the Java's

for (int i = 0; i <= 5; i ++) {
  statement
}

As you can see, the increment isn't specified in the Scala version, because Scala uses a default increment with +1. But you can add some increment-policy to the Range:

for (i <- 0 to 5 by 2) {
  statement
}

which would lead to executions with i having the values 0, 2 and 4.

Using a policy, decrements are possible, too:

for (i <- 5 to 0 by -1) {
  statement
}

Ranges aren't limited to integer numbers but can be used with floating point numbers (and floating point increments), too.

Filter

Within a for-loop some filters can be applied:

for (i <- 0 to 100 if i % 2 == 0; if i % 3 == 0) {
  statement
}

This examples shows a loop that will be executed each time i is less or equal to 100 and is a multiple of 6 (checked by two different filters). To omit the semicolon, the parantheses can be replaced by curly braces and then the single statements can also be separated by linebreaks:

for {i <- 0 to 100
    if i % 2 == 0
    if i % 3 == 0} {
  statement
}

Nested loop

Instead of using two nested for-loops, this can be done by one for-loop declaring two variables:

val lists = List(List(0, 1, 2, 3), List(-5, -3, 7), List(5), List(42, 23))
for {list <- lists
    if list.length > 1
    el <- list
    if el > 0} {
  println(el)
}

In this example the List of Lists gets iterated and every list containing more than one element (which means that List(5) is skipped) gets iterated and finally every positive element gets handled and therefore printed.

for {x <- 0 to 100
    y <- x to 100} {
  statement
}

Functional alternative

Using Scala's functional aspects for-loops also can be written without any loop:

(0 to 5).foreach(println)

If you want to apply some function to every value of the 'counter'-variable, you can also declare the Range and than pass the function and let the Range apply the function to each element.

Or you can use the values to instantiate some class within some new Collection:

scala> class Value(i: Int) {def get = i; override def toString() = "Value(" + i + ")"}
defined class Value

scala> (1 to 3).map(new Value(_)).toList
res2: List[Value] = List(Value(1), Value(2), Value(3))

The map-function returns some (list-like) Collection; the toList-function then returns a List.

Functions

Functions

def add(x: Int, y: Int): Int = x + y
def nextRandomInt(): Int = { ... }
def getValue: Int = { ... }
def setValue(value: Int): Unit = { ... }  // return-type Unit explicit
def applyFunction(f: (Int, Int) => Int)(x: Int, y: Int): Int = {
  f(x, y)
}

def exampleCalls = {                      // return-type Unit implicit
  val result = applyFunction((x: Int, y: Int) => x + y)(4, 5)
  val random = nextRandomInt()   // with optional braces
  val someValue = getValue
}

def difference(a:Int, b:Int): Int = {
  val rawDiff = a - b
  if (rawDiff < 0)   // the return-value is the result of this if expression
    -rawDiff
  else
    rawDiff
}

def gcd(x: Int, y: Int): Int = {
  if (y == 0) x else gcd(y, x % y)
}

Function Definition and Usage

To define a function you need the keyword def:

As a consequence of the fact that nearly everything in Scala is an expression, you don't need the keyword return to specify the return-value. The function-body is the return-value. If your function is built up of multiple statements, the last one specifies the return-value (difference-example).

If your function should not have any return-value you can set the return-type to Unit (the Scala equivalence to Java's void):

If the compiler can determine the function-body's result-type you can omit the return-type.

If your function doesn't have any parameters you can omit the braces, but the function's behavior depends on the kind of declaration:

Scala supports higher-order functions. That means that one function (applyFunction) can accept another function (e.g. add or the given lambda-expression) as parameter. A function can be passed to another function by naming the function and omitting the braces. This works well for functions with braces at definition. For functions without braces you have to define some kind of anonymus function using the underscore (for example getValue _).

Function Types

A function can be represented by it's type. This type describes the argument types and return type:

Function-Type  ::= FunctionArgs '=>' ReturnType
FunctionArgs   ::= '(' [ ParamType {',' ParamType } ] ')'

Examples:

Functions can be defined anonymously like the first parameter of the applyFunction-application in exampleCalls. The lambda-expression defined here is equivalent to the add function. As you can see, you define a lambda-expression by declaring the typed function-arguments and the function-body.

To apply a given function just pass the arguments to the function as you would do it with other defined functions.

Currying

A function-definition can have multiple braces with multiple arguments (as in the applyFunction-example). This leads to functions that will be executed in several steps. If we take a look at applyFunction: First, a "calculation rule" is passed to the function, which results in some mathematical function; Then the arguments can be passed to evaluate the function's result.

Functions can be defined nested. That means that you can define a function inside another function. The nested definition is only visible inside the surrounding function.

Classes

Classes

class Rational(n: Int, d: Int) {
  private val g = gcd(n, d)
  val numerator: Int = n / g
  val denominator: Int = d / g
  private def gcd(x: Int, y: Int): Int = {
    if (x == 0) y
    else if (x < 0) gcd(-x, y)
    else if (y < 0) -gcd(x, -y)
    else gcd(y % x, x)
  }
  def +(r: Rational) =
    new Rational(numerator * r.denominator + r.numerator * denominator, 
	denominator * r.denominator)
  def -(r: Rational) =
    new Rational(numerator * r.denominator - r.numerator * denominator, 
	denominator * r.denominator)
  def *(r: Rational) = new Rational(numerator * r.numerator, 
    denominator * r.denominator)
  def /(r: Rational) = new Rational(numerator * r.denominator, 
    denominator * r.numerator)
  override def toString = numerator + "/" + denominator
}

The example is taken from Odersky, M.(2011). Scala by Example If you would like to get a more thorough understanding of the example (and further refined versions of it), feel free to skim over its sixth chapter.
The fields numerator and denominator are defined as values, but could have been defined as parameterless methods as well: def numerator : Int = n / g. The difference is, that as a value, the right-hand side is evaluated when the object is created and the method evaluates every time it is called.

Objects

Singleton objects

object Rational {
  def apply(n: Int, d: Int) = {
    new Rational(n, d)
  }
}
object printRational extends App {
  val one_half = Rational(1, 2)
  println(one_half)
}

Classes and objects can have the same name. If they are in the same source file, then the object is called a companion object and the class companion class. A companion object can access its classes private fields et vice versa. Scala classes cannot have static members. Any static methods you would have written in Java go into Singleton object(s) in Scala (the Java analogy to a companion object in Scala would be a class with static methods). They are invoked via the objects name, followed by a dot and the function name.

Objects do not define a type!

Case Classes

Case Classes

  • case modifier makes the compiler add some things to your class

    • a factory method
    • 'natural' implementations of toString, equals and hashCode
    • all arguments in parameter list get a val prefix, i.e. they are visible from the outside and cannot be reassigned
    • support arbitrarily deep pattern matching, i.e. the members of an object are checked for further patterns
scala> case class Address(street:String)
defined class Address

scala> case class Employee(address:Address)
defined class Employee

scala> val person = Employee(new Address("Sesamestreet"))
person: Employee = Employee(Address(Sesamestreet))

scala> person match {case Employee(Address(street))=>println(street)}
Sesamestreet

Traits

Traits

  • Collection of behaviour and state

  • A trait with only abstract members translates directly to a Java interface

  • Mixin composition allows to take the members of a class and add the members of (multiple) traits to it without running into the diamond-inheritance problem

  • Traits can add new functionality to an unspecified superclass

Traits

abstract class Robot {

}
class Android extends Robot {
  def calculate(s: String) = "Calculating " + s
}
trait GenuinePeoplePersonality extends Robot {
  def nag(s: String) = s + "...I feel bored and depressed!"
}
object TestMarvin extends App {
  val Marvin = new Android with GenuinePeoplePersonality   
  val calculateWithGPP = Marvin.calculate _ andThen Marvin.nag _
  println(calculateWithGPP("1+1")) 
  //Calculating 1+1...I feel bored and depressed
}

"Mixin-class composition allows the programmers to reuse the delta of a class definition, i.e. all new definitions that are not inherited" (A Tour of Scala)

Traits versus abstract classes

  • One class can extend several traits using the with keyword
  • Abstract classes can take parameters - traits do not have constructors
  • Subclassing traits in Java code can be awkward
  • When a trait gains or loses a member, any classes that inherit from it must be recompiled

Keep traits short and try to express the smallest related idea possible to achieve greater modularization!

Inheritance

Inheritance

  • Compiler assumes that all classes extend scala.AnyRef
  • As in Java A extends B means, that

    • A becomes a subtype of B
    • A inherits all non-private members from B
    • A overrides members of B with the same name and parameters
    • A implements members of B if they are abstract
  • (Subtyping) polymorphism and dynamic binding as you would expect it coming from Java

Inheritance

  • abstract modifier is mandatory for classes with abstract members
  • abstract modifier is not necessary or allowed for abstract methods (no body or no '=')
  • override modifier is

    • optional if a member implements an abstract member with the same name
    • required if a member overrides a concrete member in a parent class
    • forbidden if a member does not override or implement some other member
  • final members cannot be overridden
  • Invoking superclass constructors is straightforward

    ...extends B(someValue)...
    

Inheritance

  • TODO Scala has two namespaces for defining

    • values (fields, methods, packages and singleton objects)
    • types (class and trait names)
    • class fubar{
      	val f = 0
      	def f = 1
      }///won´t compile!
      

Enums

Enums

object WeekDay extends Enumeration {
  type Operator = Value
  val Mon, Tue, Wed, Thu, Fri, Sat, Sun = Value
}

object Size extends Enumeration {
  type Size = Value
  val Small = Value("S")
  val Medium = Value("M")
  val Large = Value("L")
}

Java offers built-in support for enum-types, so that you can define something like:

public enum WeekDay {
  Mon, Tue, Wed, Thu, Fri, Sat, Sun;
}

This comes like some sort of special class. Scala hasn't something like a class-type enum but Scala also supports Enums. In Scala you simply extend the class Enumeration and create a value for every element and initialize it with Value.

The type-declaration is a simple type-alias so that you can write Mon instead of WeekDay.Mon.

If you define an enum like in the WeekEnd-example (taken from the Scala Api) each element has a String-representation equivalent to the given name. If you want some other kind of representation, you can define the elements together with a specific String like in the Size-example.

Generics

Generics

val list = List[Number](new Integer(42))
val extendedList = new Integer(23) :: list

def printAlias[T <: Any](arg: T) = println(arg)

def printAll(list: List[Number]): Unit = {
  list match {
    case hd :: tl =>
      printAlias(hd)
      printAll(tl)
    case List() => ()
  }
}

def addToCollection[T <: Number](el: T, list: List[Number]): List[Number] = {
  el :: list
}

val longestList = addToCollection[Integer](new Integer(0), extendedList)

printAll(longestList)
// returns: 0, 23, 42 (one line each)

Generics in Scala are semantically identical to Java. The notation differs from each other:

Scala offers the possibility to define types and to (re-)use them later. This types can be generic, too, like in the example of collType.

Pattern Matching

Pattern Matching

Basics

val SpecialCase = ...
var intValue: Int = ...
intValue match {
  case SpecialCase => println("number is " + SpecialCase)
  case 1 => println("number is 1")
  case 2 => println("number is 2")
  case 3 | 4 => println("number is 3 or 4")
  case _ => println("number wasn't between 1 and 4 or " + SpecialCase)
}

var someValue: AnyVal = ...
someValue match {
  case i: Int => println("value is an integer: " + i)
  case b: Boolean => println("value is bool: " + b)
  case c: Char => println("value is a char: " + c)
  case _: Double | _: Float => println("value is some floating point number!")
  case ref => println("type couldn't be determined! " + ref.getClass())
}

Pattern matching is a very powerful variant of Java's switch-statement.

Different to Java, exactly one case will always get executed. If two patterns would fit, the first one gets executed.

You can use pattern matching like switch-statements in Java (first example).
Note that the value SpecialCase starts with a upper letter and that otherwise the case-clause wouldn't work as expected (the compiler could not find the value otherwise). You can combine several pattern using '|' so that the case is executed if at least one of the pattern matches the given argument. The last pattern case _ is the Scala equivalent to Java's default.

You can use pattern matching as a clean solution for type-checking instead of instanceof-checks (for example for value-types as shown in the second example).
If the given value is of type Int the first case matches and gets executed and the (Int-)value is accessible via the identifier i. If you only need the type but not the actual value, you can use the wildcard _ (Float-example). The default case can be 'named', too, like in the ref-line, so that you can try some further (manual) checks.

In addition to the patterns you can use so-called guards (additional conditions) for further specification.
You can replace the case i: Int ...-line by the following ones to identify integer together with there sign:

  case 0 => println("value was zero!")
  case i: Int if i > 0 => println("value was a positive integer: " + i)
  case i: Int => println("value was a negative integer: " + i)

The last case only gets executed for negative integer because positive integer and zero are handled previously and, as said above, only one case gets executed.

Pattern Matching

Advanced

case class CaseClass(i: Int, s: String)
case class RecCaseClass(c: RecCaseClass = null)

var someRef: AnyRef = ...
someRef match {
  case hd :: Nil => Nil
  case hd :: 7 :: tl => hd :: tl
  case CaseClass(0, "") => CaseClass(1, "initial text")
  case CaseClass(no, "inc") => CaseClass(no + 1, "inc")
  case CaseClass(no, "dec") if no > 1 => CaseClass(no - 1, "dec")
  case CaseClass(42, _) => CaseClass(42, "the answer")
  case c @CaseClass(_, _) => CaseClass(c.s.toInt, c.i.toString)
  case RecCaseClass(RecCaseClass(content)) => content
  case default => default
}

val hd :: tl = List(1, 2, 3) // hd = 1; tl = List(2, 3)
val _ :: el :: _ = List(1, 2, 3) // el = 2
val CaseClass(i, s) = CaseClass(18, "adult") // i = 18, s = "adult"
val (t1, _, t2) = (9, 5, 1) // t1 = 9, t2 = 1

Besides the value and the type, the structure of some variable can be matched:

  1. for lists with exactly one element the empty list can be returned
  2. for lists with some specific element at some specific position, some modifications can be applied (e.g. this element can be removed)
  3. for case classes with specific parameters, a completely different instance can be constructed
  4. for case classes with some specific parameter, some other parameter can be influenced
  5. for case classes with some specific parameter and some additional condition, some other parameter can be influenced
  6. for case classes with some specific parameter, some other parameter can be replaced
  7. you can bind the whole pattern to some name while matching some class (and possibly some parameters, too)
  8. you can match some deep structure and deconstruct it
  9. you can simply return the argument if no pattern matched

Pattern matching works also outside of match-statements:

Visibility

Visibility

class Visibility {
  private val id = ...
  protected var name = ...
  def compare(v: Visibility): Int = {
    id - v.id // works (v.id is accessed within the defining class)
  }
  def copyNameFrom(v: Visibility) = {
    name = v.name // works (v.name is accessed within the defining class)
  }
}

class Subtype extends Visibility {
  def getName = name // works (is equivalent to this.name)
  override def copyNameFrom(v: Visibility) = {
    name = v.name // would not work (v.name is not accessible)
  }
}

Definitions of classes, traits, objects and members of this definitions (functions, attributes, etc) are public by default. But the visibility (and thereby the accessibility) can be limited to private or protected visibility. The visibilities are defined similarly to Java with some small differences:

At this point of knowledge, Scala seems less powerful than Java, but Scala offers the possibility to parameterize a visibility-modifier:

The same parameters are allowed for the private modifier, but private[scope] can be more stricly than protected[scope]:

Note that Scala interprets packages in some kind of hierachy: Assume you have a package called outerPackage and you define a package outerPackage.innerPackage the innerPackage is a sub-package of the outerPackage and therefore classes in the innerPackage can access members of outerpackage with 'package' visibility, which would not be possible in Java.

Exception Handling

Exception Handling

In Scala all exceptions are unchecked and usually caught via pattern matching

try {
  PreparedStatement stmt =
    conn.prepareStatement("INSERT INTO urls (url) VALUES (?)")
  stmt.setObject(1, new URL("http://www.codecommit.com"))
  stmt.executeUpdate()
  stmt.close()
} catch {
  case e: SQLException => println("Database error")
  case e: MalformedURLException => println("Bad URL")
  case e => {
    println("Some other exception type:")
    e.printStackTrace()
  }
} finally {
  conn.close()
}

see Scala for Java Refugees Part 4: Pattern Matching and Exceptions

Catching all Throwables with case e => ... or case _ = ... however is error-prone and should be avoided by any means. Control structures like break or continuations use ControlThrowables for flow control, so simply catching all Throwables would possibly break the code. Let us have a look at a piece of code from Spiros Tzavellas Blog showing another reason, why you really should not catch all Throwables:

def containsEven(nums: String*): Boolean = {
  try {
    for (i <- nums) {
      if (i.toInt % 2 == 0)
        return true
    }
  } catch { case e => () }
  false
}

You would expect the code to take an arbitrary number of strings and return true, if there is an even number among them, right?

Unfortunately, it always returns false, because the body of the for loop throws a NonLocalReturnControl that is caught by the enclosing try block. That is because the for loop actually calls foreach on nums and passes the body of the for loop as a closure, in this case a Function1. Because of the return, the closure triggers the return of the enclosing method instead of returning at the point of invocation. This is called a non-local return and is vital for control-flow abstractions using closures. To fix the issue, we would better specify the exception that should be caught: case e : NumberFormatException.

If you have to catch Throwable for some reason by all means, the correct way to do it is to re-throw any ControlThrowable in the catch-block.

Frequently used types

Frequently used types

val tuple = (42, 23, true, "Foo")
val result = tuple._1 + tuple._2
def swap(t: (Int, Int)): (Int, Int) = (t._2, t._1)

val o1: Option[Double] = Some(4.5)
val o2: Option[Any] = Nones
def matchOption[T <: AnyRef](opt: Option[T], default: T): T = {
  opt match {
    case None => default
    case Some(obj) => obj
  }
}
matchOption(o1, 2.7) // returns 4.5
matchOption(o2, "!") // returns "!"

val e1: Either[Int, String] = Left(42)
val e2: Either[Int, Bool] = Right(true)
def handleEitherWithIntAsLeftSide(e: Either[Int, _]) = {
  e match {
    case Left(i) => println(i)
    case Right(_) => println("No Left-side given!")
  }
}
handleEitherWithIntAsLeftSide(e1) // prints 42
handleEitherWithIntAsLeftSide(e2) // prints "No Left-side given!"

Scala offers some very simple but powerful types:

Tuple

In Scala you can pack multiple (1 to 22) values into one object, a so-called tuple.

The values, the tuple is built from, can be of different types and accessing one of this values will return the correct type. The compiler remembers, that:

To access some value from a tuple, the tuple offeres some attributes _1, _2, ... depending on the number of values given at creation-time.

A method can take and return tuples and hence there is no need of defining any return-value-data-container, a method somehow can return mutliple values and not just one (swap-example)

Option

Scala offers the generic type Option[A] that is inspired by the Null Object pattern. An instance of Option[A] can either be None or Some(A). Lets take a method with return-type Option[A] as example:

The caller now can get such an optional return-value and depending on the kind of return-value can act in different ways (e.g. via pattern matching).

Either

The third type presented here is the generic type Either[A, B]. An instance of Either[A, B] can either be Left(A) or Right(B). Very similar to Option the value can have two completely different 'types', but by using Either you can for example return either some value or an exception (or message) (Option only offered the possibility to indicate failure, Either additionally can give further information).

Examples

A repeat Abstraction in Scala

Policy: Repeat the same operation n-times and store the results in an array.

object RepeatAbstraction {
  def repeat[T: scala.reflect.ClassTag](times: Int)(f: ⇒ T): Array[T] = {
    val array = new Array[T](times)
    var i = 0
    while (i < times) { array(i) = f ; i += 1 }
    array
} }

Example usage (e.g., using the Scala REPL):

import RepeatAbstraction._

val result: Array[Int] = repeat(3) { System.in.read() }
// Long version:
// val body /*: () ⇒ Int*/ = () ⇒ { System.in.read() }
// val result : Array[Int] = repeat(3)(/*f =*/ body())

println("Charcodes: "+result.mkString(" "))

This solution allows us to reuse our low-level mechanism.