Skip to content

Syntax

Entry point (main)

The entry point of a Scala program (the main function) should be defined inside an object as a function named main.

object ScalaEx{
  def main(args: Array[String]) {
    println("Hello world")
  }
}

Run code

# To compile and run in the terminal
scalac ScalaEx.scala
# or
scala ScalaEx

import

import scala.math._       // imports all function from the scala.math library

Variables & Values

In scala, you can define a variable by using the var keyword:

var number : Float = 0
number = 6.0
number += 4
println(number) // Float = 10.0

Scala is able to infer the type automatically. You don't need to specify it if the variable is assigned at declaration:

var number = 0   //The type of 'number' is inferred as a Int during the compilation.

Constants

But, in fact, it's not very common to use var in Scala. Instead, constant values defined by val are often used:

val two   = 2
val three = 3
val six   = two * three

Strings

val name = "strings are cool"
println("index 3 is: " + name(3))                // index
println("length is: " + name.length)             // length
println(name.concat(" add this")                 // concat
println("index of cool" + name.indexOf("cool"))  // indexOf

nameArray = name.toArray
for(v <- nameArray)
  println(v)

Special characters

Character Description
\a audible alert
\b backspace
\f form feed
\n newline
\r carriage return
\v vertical tab
\\ backslash
$$ dollarsign
%% percentsign
""" " """ Doublequote escape

String Interpolators

%[align][sign][fill][width][.precision]type
    |      |     |    (int)     (int)  d decimal (integer) (base 10)
    |      |     |                     i integer (base 10)
    |      |     +-- void (default)    o octal number (base 8)
    |      |     +-- <any character>   u unsigned decimal (integer) number
    |      |                           x hexadecimal number (base 16)
    |      +-- + (default)             f floating point number
    |      +-- -                       e exponential floating-point number
    |                                  c character
    +-- void (default) right aligned   s string of characters
    +-- - left aligned

s-Interpolator

s"" is a procesed string literal.

val name = "Maja"
println(s"Hello, $name")     // insert variable

println(s"1 + 1 = ${1 + 1}") // insert arbitrary expression

println(s"$$15.95")          // $ escape character

val person = """{"name":"James"}""" // Double Quote escape character

f-Interpolator

f"" allows the creation of formatted strings

raw-Interpolator

Print

val name = "string"
val integer = 39
val floatingpoint = 12.3

println(s"String is $name")
println(f"$(integer)+1 $floatingpoint%.2f")
println("'%-5s'\n", "other string")

Functions

For example, if you want to define a function which returns true if the sum of its two arguments is bigger than zero, you can do as follows:

def sumBiggerThanZero(a: Float, b: Float): Boolean = {
  return (a + b) > 0
}

Then, to call this function, you can just write:

sumBiggerThanZero(2.3f, 5.4f)

You can also specify arguements by name, which is useful if you have many arguements:

sumBiggerThanZero(
  a = 2.3f,
  b = 5.4f
)

Return

The return keyword is not necessary. In absence of it, Scala takes the last statement of your function as the returned value.

def sumBiggerThanZero(a: Float, b: Float): Boolean = {
  (a + b) > 0
}

Return type inferation

Scala is able to automatically infer the return type. You don't need to specify it:

def sumBiggerThanZero(a: Float, b: Float) = {
  (a + b) > 0
}

Multiple return values

Multiple return values can be given with the help of a tuple

def mv: (Int, Int, Int) = {
  (1,2,3)
}

val (i, j, k) = mv()

Function that returns nothing Unit

If you want a function to return nothing, the return type should be set to Unit. It's equivalent to the C/C++ void.

def printer(): Unit = {
  println("1234")
  println("5678")
}

Arguments default value

You can specify a default value for each arguement of a function:

def sumBiggerThanZero(a: Float, b: Float = 0.0f) = {
  (a + b) > 0
}

Apply Function

Functions named apply are special because you can call them without having to type their name:

class Array(){
  def apply(index: Int): Int = index + 3
}

val array = new Array()
val value = array(4)   //array(4) is interpreted as array.apply(4) and will return 7

This concept is also applicable for scala object (static)

object MajorityVote{
  def apply(value: Int): Int = ...
}

val value = MajorityVote(4) // Will call MajorityVote.apply(4)

Recursion

Function which calls it self.

def factorial(num: BigInt) : BigInt = {
  if (num <= 1)
    1
  else
    num * factorial(num-1)
}

println("Factorial of 4 = " + factorial(4))

Object

In scala, there is no static keyword. In place of that, there is object. Everything defined into an object is static.

The following example defines a static function named pow2 which takes a floating point value as parameter and returns a floating point as well.

object MathUtils{
  def pow2(value: Float): Float = value*value
}

Then you can call it by writing:

MathUtils.pow2(42.0f)

Class

The class syntax is very similar to Java. Imagine that you want to define a Color class which takes as construction parameters three Float values (r,g,b) :

class Color(r: Float, g: Float, b: Float){
  def getGrayLevel(): Float = r * 0.3f + g * 0.4f + b *0.4f
}

Then, to instantiate the class from the previous example and use its getGrayLevel function:

val blue = new Color(0, 0, 1)
val grayLevelOfBlue = blue.getGrayLevel()

Be careful, if you want to access a construction parameter of the class from the outside, this construction parameter should be defined as a val:

class Color(val r: Float, val g: Float, val b: Float){ ... }
...
val blue = new Color(0, 0, 1)
val redLevelOfBlue = blue.r

Inheritance extends

As an example, suppose that you want to define two classes, Rectangle and Square, which extend the class Shape:

class Shape{
  def getArea(): Float
}

class Square(sideLength: Float) extends Shape {
  override def getArea() = sideLength * sideLength
}

class Rectangle(width: Float, height: Float) extends Shape {
  override def getArea() = width * height
}

Case class

Case class is an alternative way of declaring classes.

case class Rectangle(width: Float, height: Float) extends Shape {
  override def getArea() = width * height
}

Then there are some differences between case class and class :

  • case classes don't need the new keyword to be instantiated
  • construction parameters are accessible from outside, you don't need to define them as val.

Templates / Type parameterization

Imagine you want to design a class which is a queue of a given datatype, in that case you need to provide a type parameter to the class:

class  Queue[T](){
  def push(that: T) : Unit = ...
  def pop(): T = ...
}

If you want to restrict the T type to be a sub class of a given type (for example Shape), you can use the <: Shape syntax :

class Shape() {
    def getArea(): Float
}
class Rectangle() extends Shape { ... }

class  Queue[T <: Shape](){
  def push(that: T): Unit = ...
  def pop(): T = ...
}

The same is possible for functions:

def doSomething[T <: Shape](shape: T): Something = { shape.getArea() }