Scala Programming Langauge

16 October 2017

Introduction to Scala

Extended name of Scala is “Scalable Language” which was designed and developed by Martin Odersky.It is a Multi-Paradigm Programming Language, which supports both Object-Oriented and Functional Programming concepts.

It is strong and statically typed system which means that all types are checked at compile time by Scala compiler.

Functional Programming (FP) Concepts in Scala

It is a programming style that uses functions as building block and avoids mutable variables ,loops, and other imperative control structures .

It has below properties .

  • In FP , functions are treated as first class citizens which has the same status as variable or value.Using FP we can use functions just like a variable.
  • Functional programming emphasize the use of immutable data structures rather than using mutable data structures or variable .
  • In functional programming every statement is an expression that returns a value.
  • It supports Higher order functions through which you can pass functions as parameters
  • It provides a lightweight syntax for defining anonymous functions
  • It supports higher-order functions ,supports nested functions and supports currying
  • Pattern Matching using Case Classes : Scala case class has built-in support for pattern matching model algebraic types.
  • Singleton objects provide a convenient way to group functions that aren’t members of a class.
  • Immutability :

In Functional Programming you tend not to have classes whose state can be changed — the so-called mutable classes. Rather, your model is represented by immutable classes. Scala offers a nice syntax to create them that falls under the name of case classes.

Class and Object in Scala

An example of class in Scala .

class NewClass(x:Int ,y: Int) { //Defines a new MyClass with a Constructor
  require(y > 0, "y must be positive") //precondition triggering an IllegalArgument if not Met

  def nb1 = x               //public method which is computed every time it is called
  def nb2 = y
  private def test(a:Int):Int= { a} //Private Method
  val nb3 = x+y   //Computed Only Once

  override def toString =
    x+","+y
}
val newClass = new NewClass(2,2)
println(newClass.nb1)

Create a runnable application in Scala

There are two ways of creating runnable application in

  • Using the main method
object ScalaApplication {

def main(args:Array[String]) = println(" Hello World")
}

  • Extending App
object ScalaApplication extends App {
println("Hello World)
}

Object Hierarchy in Scala

  • scala.Any is base type of all types .It Has Methods like hasCode and toString that can be overridden.

  • scala.AnyVal is base type of all primitive types. (scala.Double ,scala.Float )

  • scala.AnyRef is a base type of all reference type. ( alias of java.lang.Object, supertype of java.lang.String , scala.List or any user defined types)

  • scala.Null is a subtype of any scala.AnyRef (null is the only instance of type Null) ,and scala.Nothing is a subtype of any other type without any instance.

Case Class in Scala

A Case class is a class with a case modifier.

Case classes are used to conveniently store and match on the contents of a class.

case class Person(name: String ,address: String)

//Create Instance of Case Class
val person = Person("Nitendra Gautam", "Dallas")

Following are Case Classes properties

  • Case Classes can be constructed without using new Keyword.
  • All input parameters specified in the definition of a case class implicitly get a val prefix.
  • Scala adds four methods such as toString, hashCode, equals, and copy to a case class.
  • Scala case classes can be used for Pattern Matching as they create a non-mutable objects

Pattern Matching in Scala

One simple use of pattern matching is as a replacement for a multi-level if-else statement. An if-else statement with more than two branches becomes harder to read.

Lets take a simple function that takes an input parameters a string which represents a color and returns 1 if the input String is “Red” ,2 for “Blue”, 3 for “Green” ,4 for “Yellow” and 0 for any other color.


def matchColorToNumber(color:String) :Int = {
     val num = color match {
      case "Red" => 1
      case "Blue" =>2
      case "Green" =>3
      case "Yellow" =>4
      case _ => 0     
    }   
     num
  }

Instead of the keyword switch, Scala uses the keyword match. Each possible match is preceded by the keyword case. If there is a match for a case, the code on the right-hand side of the right arrow is executed. The underscore represents the default case. If none of the prior cases match, the code for the default case is executed.

Another example of case class is given below. Final results is based upon the given operator like addition ,subtraction ,multiplication and division.


def executeOperation(x:Int ,y: Int ,operator: String) :Double = {
    operator match {
      case "+" => x+y
      case "-" => x-y
      case "*" => x*y
      case "/" => (x/y).toDouble
      case _ => 0 //returns 0 if empty operator
    }
  }

(someList: List[T]) match {
 case Nil => ...   //Empty List
 case x:: Nil => //List with only one Element
 case List(x) => //Same as above
 case x :: xs => ... // a List with at least one element .x is bound to the head 
 //xs is bound to the tail .xs could be Nil of Some other List.
 
 case 1 :: 2 :: cs => ... lists that start with 1 and then 2
 case (x, y) :: ps => //a list where head element is a pair
 case _ => ...  //Default case if none of the above matches 
}

Companion Object in Scala

Scala does not have static methods or variables but rather they have a singleton object or Companion object.Companion objects are compiled into classes which have static methods .


object HelloWorld {

def main(args:Array[String]){
println("Hello World")
}
}

Trait and Abstract Class

Scala traits are similar to Java Interfaces. Unlike a Java Interface a Scala trait can include implementation of a method.In addition to this a Scala trait can include fields but Scala class can reuse the fields and methods implemented in a trait.

A class can only extend one other class, but an unlimited number of traits.

While traits only support type parameters, abstract classes can have constructor parameters. A trait looks similar to an abstract class as it both contains fields and methods. The key difference is that a class can inherit from only one class ,but it can inherit from any number of traits.

Example of trait.

trait Shape {

def shapeArea(): Int

}

class Square(length: Int) extends Shape {

def shapeArea = length * length
}

class Rectangle(length: Int ,Width: Int) extends Shape {
def shapeArea = length * width;
}

val square = new Square(10)

val area = square.shapeArea

Basic Data Types in Scala

Below figure shows the basic data types in scala.

scala data types

Scala does not have the primitive data types. Scala data types are converted into primitive types by scala compiler whenever possible to optimize application performance.Each data type in Scala is implemented as a class.

Scala Variables

Scala has two types of variable .

Mutable Variable (var)

var x = 30
x =20 // Value of Var can be changed 

Immutable variable (val)

val y = 20
y =10    //Compiler will throw an error as value of val cannot be reassigned

Scala is statically language because of which everything has a type in scala.

But Scala infers the type of variable whenever possible without forcing the developers to declare it .

Below two statements mean the same thing .

val y =20
val y: Int = 20

Type Inference” in Scala

Types can be inferred by the Scala Compiler at compile-time. It is known as “Type Inference”. Types means Data type or Result type. We use Types at many places in Scala programs like Variable types, Object types, Method/Function Parameter types, Method/Function return types etc.

In simple words, determining the type of a variable or expression or object etc at compile-time by compiler is known as “Type Inference”.

class MyClass[T](arg1: T) { ... }
new MyClass[Int](1)
new MyClass(1) // Here type is being inferred ,i.e. determined based on value arguments

Functions in Scala

Function is a block of executable code that returns a value .

Function in scala can be defined inside another function .It can be returned as an output from another function.

//add function in scala which takes two parameters of type Int and returns Int
def add(value1: Int ,value2: Int ): Int = {
    val sum = value1 +value2;
    sum
}

Use Scala we can write above code concisely .

def add(value1: Int ,value2: Int) = value1 + value2

Methods in Scala

Methods in Scala is a function that is a member of an object . A method has access to all the fields of the object to which it belongs.

Local Functions

Local functions are functions which are defined inside the function .This function will have access to variables defined within that specific functions.

Higher order Functions

A method that takes a function as an input parameter is called a higher-order method.

Higher Order function is a function that takes another function as input.

def encode(n: Int, f: (Int) => Long): Long = {
val x = n * 10;
f(x)
}


//Sum() returns a function that takes two Integer and Returns an Integer
  def sum(f: Int => Int):(Int, Int) => Int ={
    def sumf(a: Int ,b:Int): Int ={
      a+b
    }
    sumf
  }

//Same as Above .
//Its type is (Int => Int) => (Int ,Int) => Int
  def sum(f:Int => Int)(a:Int ,b:Int):Int = a+b

//Called like this
sum(x: Int) => x * x * x) //Anonmous Function which does not have a name

sum(x => x * x * x)    //Same anonymous function with type inferred


def cube(x: Int) = x * x * x
sum (x => x * x * x)(1, 10) //Sum of cubes from 1 to 10

sum(cube) (1 ,10) //Same as above

Currying in Scala

Currying is a technique of making a function that takes multiple arguments into a series of functions that take a part of the arguments.Currying is useful in many different contexts, but most often when you have to deal with Higher order functions.

def addition1(firstNum: Int)(secondNum: Int) = a + b
val addition2 = addition1(2)(_)
scala> addition2(3)
res0: Int = 5
def f(a: Int ,b: Int): Int = a+b  //uncurried version where( type is (Int ,Int) => Int)

def f(a: Int)(b: Int) : Int //Curried Version ( Type is Int => Int =>)

Scala List vs Java List

There is vast difference between Scala’s List scala.List and Java’s list java.util.List.

Scala Lists are always immutable whereas Java Lists can be mutable. Scala’s List is designed to enable a functional style of programming .

We can use the Scala’s List class for immutable sequence of objects that share the same type As with arrays, a List[String] contains only strings.

Scala Future vs Java Future

With scala.concurrent.Future we get instead a real non-blocking computation, as you can attach callback for completion (success/failure).

When using java.util.concurrent.Future get() method is blocking in nature .

None ,Null Nothing, Nil in Scala

  • None is the empty representation of the Option monad

  • Null is a Scala trait, where null is its only instance. The null value comes from Java and it’s an instance of any object, i.e., it is a subtype of all reference types, but not of value types. It exists so that reference types can be assigned null and value types (like Int or Long) can’t.

  • Nothing is another Scala trait. It’s a subtype of any other type, and it has no subtypes. It exists due to the complex type system Scala has. It has zero instances. It’s the return type of a method that never returns normally, for instance, a method that always throws an exception. The reason Scala has a bottom type is tied to its ability to express variance in type parameters..

  • Nil represents an empty List of anything of size zero. Nil is of type List[Nothing].

source:

Implicit Parameters in Scala

Scala “implicits” allow you to omit calling methods or referencing variables directly but instead rely on the compiler to make the connections for you.

Options in Scala

An Option is a data type in Scala that indicates the presence or absence of some data.

It can be an instance of either case class called Some or Singleton object called None.An instance of Some can store data of any type . An instance of None object represents absence of data.

One of the common uses of this is to prevents from getting a NullPointerException in Scala . when mapping an Option without a value (None), the mapping function will just return another None.

//Assign cost as Option which means it can be either None when empty
scala> val cost: Option[Double] =None
cost: Option[Double] = None

scala> val fee = 1.25
fee: Double = 1.25

scala> cost.flatMap { x => if( x> 1.00) None else Some(x+fee) }
res18: Option[Double] = None

//Asssigning value to cost after which its value will be 0.5
scala> val cost = Some(0.5)
cost: Some[Double] = Some(0.5)

scala> cost.flatMap { x => if( x> 1.00) None else Some(x+fee) }
res19: Option[Double] = Some(1.75)

Another example of Option

def matchColorCode(color: String) : Option[Int] = {

color match {
case "red" => Some(1)
case "blue" => Some(2)
case "green" => Some(3)
case _ => None
}
}

//color "orange" is not defined
val code = colorCode("orange")

code match {

case Some(c) => println(" code for orange is: "+c)
case None = > println(" Code not defined for orange")
}


val cMap = Map("a" -> 42 ,"b" -> 43)


def getMapValues(keyValue: String):String = {
  cMap get keyValue match {  //Gets the Value which is passed through the Function
    case Some(mb) => "value found: " +mb
    case None => "No Value Found"
  }

}

getMapValues("b") //Value Found 43
getMapValues("c") //No Value Found

Another way to get Map Values using the combinator method of the Option Class

def getMapValuesC(s:String)= cMap.get(s).map("Value Found: "+ _)
.getOrElse("No Value Found")

getMapValuesC("a")  //Gets the Value 42

Function Literal

A function literal is an unnamed or anonymous function in source code. It can be used in an application just like a string literal. It can be passed as an input to a higher-order method or function. It can also be assigned to a variable.

(x: Int) => {
              x+100
             }

for a single statement we can use it in a single line.

(x: Int) => x + 200

Evaluation rules in Scala

  • Call by value : Evaluates the function arguments before calling function

  • Call by name : evaluates the function first and then evaluates the argument if needed

 def square(x: Double) = x*x  //Call by Value

def square(x: => Double) = x*x //Call by Name

def example = 2 //evaluated when called

val example = 2  //evaluated immediately

lazy val example = 2 //Evaluated once when needed

References

Scala Documentation Understanding Scala Map and Flat Map

Big Data Analytics with Spark

Share: Twitter Facebook Google+ LinkedIn
comments powered by Disqus