A Concise Introduction to Scala
Copyright © 2011, 2013 David Matuszek

Console I/O
Data Types
File I/O

Function Literals
Getting Scala
GUI Programs
Higher-order functions

Program Structure
Running Scala
Statement Types


Getting Scala

As of October 2016, these were the relevant web sites:

Running Scala

In a Java application, you need a public static void main(String[] args) method. In a Scala application, you need a def main(args: Array[String]) method.

How to run Code Results/Comments
On the command line as a REPL (Read-Eval-Print-Loop).
dave% scala
Welcome to Scala version 2.7.7.final (Java ↙ HotSpot(TM) 64-Bit Server VM, Java 1.6.0_17). Type in expressions to have them evaluated. Type :help for more information. scala> 2+2 res0: Int = 4 scala> exit

No main method is required in this case.


As a script.
println("Hello from a script.")
dave% scala HelloScript.scala
Hello from a script.
Scala automatically wraps your lines in a class and a main method, so don't do this yourself.
As an application.
object HelloApp extends App {
  println("Hello, World!")
dave% scalac hello.scala
dave% scala HelloApp
Hello, World!
File name doesn't have to be the same as the application name. The App trait wraps your code in a main method.
As a single object.
object HelloObject {
  println("In object")
  def main(args: Array[String]) {
    println("In main")
dave% scalac HelloProgram.scala
dave% scala HelloObject
In object
In main
As a program.
class HelloClass {
  def inClass() {
    println("In class")

object HelloObjectPlusClass {
  println("In object")
  def main(args: Array[String]) {
    println("In main")
    val c = new HelloClass
dave% scalac HelloWithClass.scala
dave% scala HelloObjectPlusClass
In object
In main
In class

The object may not have the same name as the class!

scalac is the compiler. You can use fsc instead, which remains in memory and so is faster (after the first use).


Scala has four types of identifiers:

Alphanumeric identifiers:
Operator identifiers:
Mixed identifiers:
Literal identifers:


All variables must be declared, with either var (if the value may change) or val (for constants). In Scala, val is preferred, unless you have good reason to use var. If given an initial value in the declaration, the variable's type is inferred and need not be explicitly stated (but it may be). If explicitly stated, the type comes after the variable and a colon, for example, var q: Boolean = true.

The types of variables must be declared:

Type parameters (generics) are enclosed in square brackets, for example, Array[Int].

Within a method, variables must be given an initial value. Variables within a class (and not within a method) may optionally be given an initial value.

When initial values are not given, new is required: val ary = new Array[Int](5)
    and default values of zero, false, or null are used.
When initial values are given, new is not allowed: val ary2 = Array(3, 1, 4, 1, 6)

The type of a function is written with the double-headed arrow, => or the Unicode version, . Except in the case of a single argument, parentheses are required:

Data types

Scala has no primitives, only objects.


Char, Byte, Short, Int, Long, Float, Double are considered to be numeric types. The default type for integers is Int, and the default type for "real" numbers is Double. The less accurate forms are converted to Int or Double when arithmetic is performed using them.

All numbers are stored internally in a binary representation, but they may be written in various ways.

Operations on numbers include + (addition), - (subtraction or negation), * (multiplication), / (division), and % (modulus). Operations on integers also include << (left shift), >> (right shift with sign extension), >>> (right shift with zero fill), & (bitwise and), | (bitwise or), and ^ (bitwise exclusive or).


A String may be enclosed in double quotes, "...", or in triple double quotes, """...""". The latter is a raw string (that is, \ does not "escape" characters) and may contain newlines.

If a triply-quoted string contains whitespace and the '|' character at the beginning of each line after the first, the method stripMargin will remove these characters. This can be use to prevent long strings in the code from messing up the code indentation.

A Symbol is an interned string. A symbol literal starts with a single quote, ', followed by a letter, then zero or more letters and digits.


Lists are the most valuable data type in any functional language, including Scala.

Much of the following information is from http://anders.janmyr.com/2009/10/lists-in-scala.html.

Lists are:

When it is necessary to specify the type of a list, write it as List[Type]. A literal list is written as List(value, ..., value).

Fundamental (efficient) list methods are:

Functions defined in terms of the above include:

Higher-order functions

The following functions are described as operations on lists, but most of them will operate on many types of sequences.


A tuple consists of from 2 to 22 comma-separated values enclosed in parentheses. Tuples are immutable. To access the n-th value in a tuple t, use the notation t._n, where n is a literal integer in the range 1 (not 0!) to 22. There may be a spaces around the dot, but not between _ and n.


Sets are immutable by default. Mutable sets may be imported from scala.collection.mutable. There are a great many operations on sets, of which contains, isEmpty, intersect, union, and diff are just a few.


Maps are immutable by default. Mutable maps may be imported from scala.collection.mutable. A map is represented as a list of pairs, that is, Map((key, value), ..., (key, value)). A more expressive syntax for writing the same thing is Map(key -> value, ..., key -> value).

The basic operations on maps are (1) getting the value associated with a key, and (2) for mutable maps, associating a value with a key. Most list operations can also be used on maps.


Options are used when an operation may or may not succeed in returning a value. Options are parameterized types, so one may have, for example, an Option[String] type. The possible values are Some(value), where the value is of the correct type, or None, for the case where no value has been found.

Although a few operations are defined for Option types, it is far more common to use a match expression to extract the value, if one exists.


Arrays are mutable. The advantage of arrays is fast access to random elements. One disadvantage is that the operations == and hashCode use the Java definitions, that is, identity rather than equality. Unless random access is needed, consider using Lists instead.

An array may be created by listing its values:

or by explicitly giving its type, and using new to indicate its size:

The basic operations on arrays are getting a value from it, storing a value in it, and getting its length. Note the use of parentheses instead of brackets.

Multidimensional arrays

To create a multidimensional array, import Array._, then call either

 The elements of a multidimensional array can be accessed using the syntax arrayName(firstIndex)(secondIndex)...(lastIndex).


If expressions

The value of the if expression is the value of the expression that is chosen; or, if no condition is satisfied and there is no else clause, the value is the Unit value, ().

For expressions (known in other languages as list comprehensions)

The for expression is used to create and return a sequence of results. The syntax is for (seq) yield expression, where:


Match expressions


expression match {
    case pattern1 => expression1
    case pattern2 => expression2
    case patternN => expressionN

The match expression uses pattern matching to select a case, then the value of the match expression is the value of the corresponding expression. Patterns may be:

Cases are tried in the order in which they occur. When a case is selected, the code for that case, and only for that one case, is executed.

Statement types

Scala does not have "statements," it has expressions, and every expression has a value. However, some expressions are executed purely for their side effects, and return the Unit value, (), which is essentially meaningless. Such expressions are basically the same as statements in other languages.

Syntax Example Comments
{ expressions } { temp = a; a = b; b = temp } A compound expression consists of one or more expressions enclosed in braces. The value of a compound expression is the value of the last expression evaluated within it; all other expressions are evaluated only for their side effects. The value of a compound expression may or may not be Unit.
var name: type = value var abc = 5 Variables must be given initial values, except when within a class.
var name: type var abc: Int Allowable within a class.
val name: type = value val five = 5 val declares a constant, which must be given a value; explicit type information is allowed but redundant. A val name for an object is constant in the sense that the name cannot be reassigned; but the contents of the object may be modified.
name = expression abc = 10 Values may be assigned only to var variables.
name += expression abc += 1 All the various op= operators are allowed. ++ and -- do not exist in Scala.
if (condition) expression
else if (condition) expression
else expression
if (x < 0) {
  x = -x
else x = x + 1
Zero or more else if clauses may be used, and the final else is optional. Braces can be used to group several expressions into a single compound expression. The value of the if is the value of the last expression evaluated within it (which may be Unit).

If there is no final else, the type of the expression is Any, regardless of whatever value it may have.
while (condition) statement
var x = 1
while (x < 1000)
  x *= 2
Nothing unusual to note. However, Scala has no break or continue statements.
do { statements } while (condition)
var x = 1
do {
  x *= 2
} while (x < 1000)
Nothing unusual to note. However, Scala has no break or continue statements.
for (variable <- list) statement
for (x <- ary)
The parenthesized expression may contain tests, assignments, and additional generators (variable <- list expressions).
for (variable <- min to max) statement
for (i <- 1 to 10)
to is a method of RichInt. to is inclusive; until excludes max.
for (variable <- min to max if condition)
for (i <- 1 to 15 if i % 2 == 0) print(i) for comprehensions may have guards.
return expression
return true

Returns a value from a method. Use of return requires that the return type of the method be explicitly stated.

throw new Exception throw new IllegalArgumentException As in Java.
try { expressions }
catch {
case name: Exception => {...} ...
case name: Exception => {...} }
finally {...}
try {
  val f = new FileReader("input.txt")
} catch {
  case ex: FileNotFoundException => {
    println("Missing file exception")
  case ex: IOException => {
    println("IO Exception")
  finally {
    println("Exiting finally...")

The Exception is the exception type, and the name is a variable holding the exception that occurred.

As in Java, you should have one or both of catch and finally; usually you won't want both.

This example is from TutorialsPoint.



If overriding an inherited method, the keyword override is required.

access may be private, protected, or public by default.

The type of each argument must be specified explicitly.

The return type of a method can usually be omitted; it must be declared:

For reasons of clarity, it is usually best to declare the return type.

Braces around the body may be omitted if the body consists of a single expression, whose value is to be returned.

Methods may be overloaded, as in Java.

The parameters of a method or function are treated as if they were defined by val; they cannot be reassigned a new value.

Function literals

Syntax: (arg1: Type1, ..., argN:TypeN) => expression

Passing function literals as arguments

Within an enclosing argument list, the parentheses around the parameter list can usually be omitted.
Example: "aBcDeF".map(x => x toLower)

If each parameter is used only once, and the parameters appear in the expression in the same order as in the parameter list, the parameter list may be omitted, and underscores may be used in the expression.
Example: "aBcDeF".map(_ toLower)

Passing methods as functions

Methods can often be passed as if they were functions, for example, "abc" map println works. In other cases, the method name must be followed by an underscore to convert it to a "partial function," for example, "abc" map (println _).

Methods are functions that belong to objects, and as such, can manipulate the fields of their object. Methods that do this should not be used as functions.

Program structure: Classes, Objects, Traits and Scripts


A script is a list of commands that can be interpreted directly by the Scala system. Scala wraps the script in a main method and executes it immediately. The syntax for running a script is simply scala myScript.scala.


A class describes objects, as in Java. A class may extend one other class, and it may include any number of traits. A class has a primary constructor, which is part of the class declaration itself.

class Foo { ... }
By default, a class extends AnyRef.
class Foo(name: String) { constructor_body }
The primary constructor is part of the class header. Parameters are put after the class name, and the constructor body is the entire class body.
class Foo(a: Int, var b: Int, val c: Int) { ... }
Constructor parameters are handled as follows. Automatically, all parameters are automatically declared as private fields; a has private getters and setters; var b has public getters and setters; and val c has a public getter. A setter method for a parameter v has the name v_=.
def this(parameters1) { this(parameters2); ... }
Auxiliary constructors are defined with this; the first statement in the auxiliary constuctor must be a call to some other constructor.
class Foo(a: Int, b: Int) extends Bar(a + b) { ... }
When extending a class, any base class (=superclass) parameters are provided immediately.
class Dog(name: String) extends Animal with Friend { ... }
A comma-separated list of traits can follow the keyword with. Any uninitialized vars and vals defined by the trait must be initialized by the class.

Case classes

A case class is defined by adding the keyword case before the word class. This results in additional methods being added to the class.


In addition to creating objects from classes, you can declare objects. An object is declared like a class, but with the keyword object instead of class; also, an object cannot take parameters. Whereas a class declaration describes a blueprint for objects, an object declaration declares a single object.

A program, other than a script, must contain an object with a main(args: Array[String]) method.

When you define a class and create objects from it, you use the keyword new:

scala> class Dog(name: String)
  defined class Dog

scala> val a = new Dog("Fido")
  a: Dog = Dog@a80370d
But when you create an object "literal", you don't use new, because these are defined as case classes.
scala> val t = Tuple(1, "apple")
t: (Int, java.lang.String) = (1,apple)

scala> val l = List(1, "apple")
l: List[Any] = List(1, apple)

scala> val s = Set(1, "apple")
s: scala.collection.immutable.Set[Any] = Set(1, apple)


Traits are declared like classes, used like Java interfaces, and may contain fully-defined methods. In the declaration of a class (or object), if the superclass is mentioned, the syntax is class ClassName extends SuperClass with Trait1,...,TraitN, otherwise the syntax is ClassName extends Trait1 with Trait2,...,TraitN



import scala.io.StdIn.readLine

val data = readLine // Reads a single line (as a String) from the Console
val data = readLine(prompt) // Prints the prompt, then reads a line

Note: In the REPL, readLine does not display the text being entered.

print(data)    // Prints to the Console without a newline
println(data)  // Prints to the Console with a newline
println        // Just prints a newline

Text files

Finding a file to read or write

Scala.swing is no longer supported.

import scala.swing.FileChooser, java.io.File
val file = new File(fileName)   // with a relative or absolute path
val chooser = new FileChooser
val response = chooser.showOpenDialog(null)  // to read a file
val response = chooser.showSaveDialog(null)  // to write a file
if (response == FileChooser.Result.Approve) {
val file =
chooser.selectedFile }

Reading from a text file

import scala.io.Source, scala.io.Source._
val stream = Source.fromFile(file or fileName)
for (char <- stream) {
process each character }
for (lines <- stream.getLines) { process each line }
val all = stream.getLines.toList         // as a list of strings
val all = stream.getLines.mkString       // as a single string
val all = stream.getLines.mkString("\n") // with newlines

Writing to a text file

import java.io.PrintWriter
val stream = new PrintWriter(file or fileName)



It is extremely important to have compatible versions of the software, otherwise you may get errors or simply have the program refuse to run.

Here are two setups that have worked for me:

Fall 2015Fall 2016
  • Scala IDE 4.0.0-vfinal-2014 (Juno)
  • Scala Library container [2.11.4]
  • JRE System Library [JavaSE-1.7]
  • scalatest_2.11-2.2.1.jar
  • Scala IDE 4.4.1-v-2016e (Neon)
  • Scala Library container [2.11.8]
  • JRE System Library [JavaSE-1.8]
  • scalatest_2.11-2.2.4.jar

And a working test file:

package fractionTest

import org.scalatest.FunSuite
import Fraction._

class ExampleTests extends FunSuite {
  val f1 = Fraction(1, 2)
  val f2 = Fraction(1, 4)
  test("Test multiplication") {
    assert(f1 * f1 == f2)
  test("Test bad multiplication") {
    assert(f1 * f2 == f2)

GUI Programs

While Java Swing can still be used from Scala, Java is moving from Swing to JavaFX, and Scala is following suit. Scala Swing is no longer being developed and is probably incompatible with current versions of Scala.