Saturday, April 28, 2018

Case classes and Pattern matching in Scala

Case classes

In Scala, a class can be defined with keyword case, and is called case class.
case class Player(name: String, sport: String, club: String)
So how is a case class different from a non-case class?
First, Scala compiler adds a factory method with same name as class. With this factory method, you can create instances of  case class without using new keyword.
var p = Player("Messi","Football","Barcelona")
Second, all arguments in parameter list of a case class are by default val, and hence maintained as fields.
Third, Scala compiler also adds natural implementations for methods toString,equals and hash. As '==' in Scala invokes equals, so instances of case classes are compared structurally.
Compiler also adds a copy method to the case class, which enables users to make modified copies of an instance. We provide modified values for named parameters, and new instance is created with  these new parameter values and values from copied instance for unspecified parameters.
val r = m.copy(name = "Ronaldo", club = "Real Madrid")
Apart from these convenient methods, biggest advantage of case classes is that they support pattern matching.

Pattern matching

Pattern matching is a mechanism by which a value is checked against a pattern.
A match expression consists of a value, match keyword and a list of case clauses.
def checkValue(x: Int) = x match {
  case 0 => "Nothing"  case 1 => "Just one"  case 2 => "Just two"  case _ => "Many"}
Here, patterns are all literals. Such patterns are called Constant patterns. A constant pattern matches to itself only.
Match expression has a type, like this one has type String as all case clauses return String.
Case '_' represents catch all case, meaning it matches any value which doesn't match to other case clauses in the list.
Case classes are easy to use in pattern matching.
abstract class Shape
case class Triangle(base: Int, height: Int) extends Shape
case class RectAngle(width: Int, height: Int) extends Shape
case class Circle(radius: Int) extends Shape
case class AnyOtherShape(name: String) extends Shape
def getShapeArea(shape: Shape): Any = {
  shape match {
    case Triangle(base, height) => (base * height) / 2    case RectAngle(width, height) => width * height
    case Circle(radius) => (Math.PI) * radius * radius
    case _ => "Can't calculate"  }
}
Above is an example of Constructor patterns.

Pattern matching can be done on type too. It may be helpful if a method is to be called on a pattern.
abstract class Automobile
case class Car(brand: String, buildYear: Int) extends Automobile{
  def getCarDescription() = s"This is a $brand, built in                                       year $buildYear"}
case class Crane(height: Int, capacity: Int) extends Automobile{
  def getCraneDescription() = s"This is a $height meters                         high, $capacity tons capacity crane"}
def getAutomobileDescription(automobile: Automobile): Any = {
  automobile match {
    case car:Car => car.getCarDescription()
    case crane:Crane => crane.getCraneDescription()
    case _ => "No description available"  }
}
println(getAutomobileDescription(Car("BMW", 2005)))
println(getAutomobileDescription(Crane(30, 1500))) 
This is called Typed pattern.

Similarly we have Sequence patterns(using Sequences), Tupled patterns(using tuples), and so on.


Saturday, April 21, 2018

Functions and Closures in Scala

In Scala, like Java, most common way of defining a function is as a member of a object. Such  a function is called Method.
object MethodDemo extends App{
  def isGreaterThan2(i: Int) = {
    println("Inside isGreaterThan2")
    i > 2  }
  println(MethodDemo.isGreaterThan2(7))
  println(MethodDemo.isGreaterThan2(1))
}

A very important part of functional programming is to decompose the program into as many small functions as possible. This makes these individual building blocks easy to understand, and enables programmers to combine these functions to do complex things with more flexibility.

First class functions


Scala not only enables defining functions as methods, but also allows to write functions as literals without any name and then pass them around as value objects.
object FirstClassFunctionDemo {
  val increment = (x: Int) => x+1
  def main(args: Array[String]): Unit = {
    println(increment(0))
  }
}
What is happening here is that Scala compiler  compiles literal function into a class extending a Scala trait Function1(as there is only one parameter), and it's 'apply' method is implemented with the body provided. During run-time, this class is instantiated as functional value and object is assigned to function variable 'increment'.
When we do:
increment(0)
It translates to:
increment.apply(0) 
'increment' is a function variable and it has a type(Int => Int), and just like any other variable it can be moved around, and assigned to other variables.
var anotherIncr = increment

Partially Applied Functions

In Scala, when we invoke a function with passed arguments, we say we apply function on the passed arguments.
val product(x: Int,y: Int,z: Int) = x * y * z
product(11,12,13)
Scala also allows to define partially applied functions.
scala> val p = product(1, _: Int, _: Int)
p: (Int, Int) => Int = $$Lambda$1134/97761958@24fe2032
In this code, we define a partially applied function,p. REPL output shows that Scala compiler generates a class extending trait Function2(meaning two input parameters), creates a function value from it and assigns it to p. Generated class's apply method takes 2 integer arguments, and invokes product with these two arguments and 1 as third argument.
scala> p(2,5)
res35: Int = 10

Closures


When we define functions in Scala, we make use of arguments which have a meaning in context of the function.
val multiplyByTwo = (x: Int) => x * 2
Here, x has a meaning in context of  'multiplyByTwo' and x is called a bound variable. Such a function literal is called close term. Scala also allows us to do following:
var factor = 1val multiply = (x: Int) => x * factorprintln(multiply(10))
factor = 2println(multiply(10))
factor doesn't have a binding from point of view of function 'multiply' here. Such a variable is called is free variable, and such a function literal is called open term because it is 'open'  to capture bindings for factor. During run time, function value created for this function literal captures the binding for factor by searching into surrounding scope. If it is not found, error is thrown. Else, the function value created is called closure, as it has now captured binding for factor and closed the open term. Also, if captured variable changes as program runs, closure always comes to know about it. So while output of first println above is 10, output of second println is 20 as change in factor is tracked by the closure. And this change tracking is in both ways. If function modifies captured variable, it is known outside the closure.

Tail recursion

Scala encourages data immutability. So traditional way of implementing some algorithms may be not preferable in Scala. For example, finding out sum of all elements in a list may seem like this:
val sumTraditional = (list: List[Int]) => {
  var sum = 0;
  for(i <- list){
    sum += i
  }
  sum
}
Functional programming discourages this style as here data is getting mutated.
Functional way of doing this would be a recursive algorithm:
def sumRecursive(list: List[Int]): Int = {
  list match {
    case Nil => 0    case x::xs => x + sumRecursive(xs)
  }
}
But recursive calls may fail if list is too big. Scala provides solution to this problem with a solution called tail recursion. Tail recursion means when last thing in the function is the recursive call. Scala compiler detects it and instead of making a new call,it jumps to start of the function after updating function parameters with new values. This compiler optimization results in no new call frame added to stack during run time. So even very big collections can be handled recursively.
@tailrecdef sumTailRecursive(list: List[Int], accumulator: Int): Int = {
  list match {
    case Nil => accumulator
    case x::xs => {
      sumTailRecursive(xs,accumulator + x)
    }
  }
}
Scala provides annotation @tailrec to check that recursive call is tail recursive or not.


Saturday, April 14, 2018

Traits in Scala

In Scala, traits are a basic mechanism of code reuse. A trait contains fields and methods which can then be reused by mixing them with classes. A class can mix in in any number of traits.

Defining a trait

A trait is defined just like a class, except that it is done with keyword trait.

trait Poet{
  def writePoem(){
    println("Twinkle Twinkle Little Star...")
  }
} 

A trait can declare a superclass,and like any other class default superclass is AnyRef.
A trait can be mixed in to a class by using keyword 'extends' or 'with'.
class BallardArtist extends Poet{
  override def toString = "I write Ballard"}
BallardArtist mixes in Poet by using keyword 'extends'. In this case, class implicitly inherits trait's superclass. So BallardArtist  subclasses AnyRef and mixes in Poet.
Methods inherited by a class from a trait are used just like methods inherited from a superclass.

val ballardArtist = new BallardArtist
ballardArtist.writePoem()
A trait also defines a type.
val poet:Poet = ballardArtist
poet.writePoem()
A class can explicitly extend a superclass with 'extends', and mix in a trait using 'with'.
class BallardArtist extends Person with Poet{
  override def toString = "I write Ballard" 
}
A class can mix in multiple traits using 'with' keyword.
class BallardArtist extends Person with Poet with Artist
 A class can override methods inherited from trait.
class BallardArtist extends Person with Poet with Artist{
  override def toString = "I write Ballard"
  override def writePoem = {
    println("Don't Tell Mama I Was Drinking...")
  }
}
From examples so far, one may incline to infer that Scala traits are similar to Java interfaces with concrete methods. But there is much difference between two. Traits can declare fields and have state.
Anything that can be done in a class can be done in trait too, with two differences.
First, class parameters can't be passed to a trait. Second, 'super' call in case of trait is dynamically bound and not statically bound like in class.

Interface Enrichment

One major benefit of trait is that as it can have concrete methods, it helps in enriching the interface of a class. Unlike interfaces where every implementing class has to provide implementations of the interface methods, trait can provide implementations to be reused by all classes which mix in the trait. With traits, classes need to implement only a small number of abstract methods(thin part of the interface) with trait itself implementing majority of the methods(rich part of the interface).
A very good example of this is Ordered trait in Scala. This trait provides a rich set of comparison methods like <,<=,>,>= etc. If developers want to provide have similar interface for their custom class, they only need to mix in Ordered trait and provide implementation for 'compare' method.Ordered already provides implementation for comparison methods mentioned above in terms of 'compare'.

Stackable behaviour with traits linearization

When we have a class hierarchy and mixed in traits, Scala puts all of them in a linear order. So,if there is a super call in one of them, next method invoked is one up this chain. With this arrangement, if all methods in this call chain call super except last one, we get a stackable behaviour.
In this linearization scheme, a class is always linearized before all of its super classes and mixed in traits.

Suppose, we have following inheritance in our ptogram
class B
trait T1 extends B
trait T2 extends B
trait T3 extends T2
class A extends B with T1 with T3
We can write our linearization scheme as:
L(A )= A+:L(T3)+:L(T1)+:L(B)
In this scheme, :+is sort of concatenation operand such that right operand replaces that part of left operand which it shares.

Linearization of individual participants is as follows:
L(B) = (B, AnyRef, Any)
L(T1) = (T1, B, AnyRef, Any)
L(T2) = (T2, B, AnyRef, Any)
L(T3) = (T3, T2, B, AnyRef, Any)

So,
L(A) = (A)+:(T3, T2, B, AnyRef, Any)+:(T1, B, AnyRef, Any)+:(B, AnyRef, Any)
L(A) = (A,T3, T2,T1, B, AnyRef, Any)+:(T1, B, AnyRef, Any)+:(B, AnyRef, Any)
L(A) = (A,T3, T2,T1, B, AnyRef, Any)+:(B, AnyRef, Any)
L(A) = (A,T3, T2,T1, B, AnyRef, Any)

When any of these classes and traits invokes a method via super, the implementation
invoked will be the first implementation to its right in the linearization.

Example:
abstract class IntQueue{
  def get(): Int
  def put(x: Int)
}
trait Doubling extends IntQueue{
  abstract override def put(x: Int){
  println("In Doubling's put")
  super.put(2*x)
 }
}
trait Incrementing extends IntQueue{
  abstract override def put(x: Int){
  println("In Incrementing's put")
  super.put(x + 1)
 }
}
class BasicIntQueue extends IntQueue{
  private val buf = new ArrayBuffer[Int]
  def get() = buf.remove(0)
  def put(x: Int) {
    println("In BasicIntQueue's put")
    buf += x
  }
}
object StackableTraitsDemo {
  def main(args: Array[String]): Unit = {
    val doublingQueue = new BasicIntQueue with Doubling
    doublingQueue.put(10)
    println(doublingQueue.get())
    val incrThendoublingQueue = new BasicIntQueue with            Doubling with Incrementing
    incrThendoublingQueue.put(10)
    println(incrThendoublingQueue.get())
    val doublingThenIncrQueue = new BasicIntQueue with            Incrementing with Doubling
    doublingThenIncrQueue.put(10)
    println(doublingThenIncrQueue.get())
 }
}
Output is as:
In Doubling's put
In BasicIntQueue's put
20
In Incrementing's put
In Doubling's put
In BasicIntQueue's put
22
In Doubling's put
In Incrementing's put
In BasicIntQueue's put
21






Saturday, April 7, 2018

By-name parameters in Scala

In Scala, when we pass parameters to a function they are evaluated before being passed. This is called by-value parameters, and it is default mechanism.

But there may be certain scenarios when we would prefer that parameters are evaluated only when they are used in function body. This helps in building custom control structures.

This is achieved by declaring parameters to be passed using by-name mechanism.

def myWhileLoop(condition: => Boolean)(body: => Unit): Unit = 
  if (condition) {
    println("Condition passed")
    body
    myWhileLoop(condition)(body)
  }

In above method, we define parameters with ': =>' instead of  ': '(space after : is necessary). This tells Scala to evaluate parameters only when used in function body. Now we can call this method as:

var i = 4myWhileLoop (i > 0) {
  println(i)
  i -= 1}  // prints 4,3,2,1

condition and body both are evaluated only when used in method body. If condition is evaluated to true, body is executed.

This is also helpful when a parameter evaluation is computationally expensive or time consuming as it ensures that evaluation happens only when needed.

By-name parameter mechanism should not be confused with lazy evaluation. Lazy evaluation happens only once when it is needed.


Currying in Scala

Currying is one of the several mechanisms in Scala to create control abstractions.

Common way of writing function is as:

def plainCommonSum(x: Int, y: Int) = x + y
This function has a single parameter list.

A curried function, on other hand, is applied to multiple argument lists. Above function when written in 'curried' manner:

def curriedSum(x: Int)(y: Int) = x + y
An invocation to a curried function is basically a sequence of traditional function invocations.For example, when we call 'curriedSum' ,first a function call takes a single Int parameter 'x', and returns a function value. A second function call is made with this function value and it takes a single Int parameter 'y',and returns an Int.

We can get reference to 'second' function by using placeholder notation.

def greetSomeOne(greeting: String)(name: String) =  greeting + " " +name
val greetHi = greetSomeOne("Hi")_ 
val greetHello = greetSomeOne("Hello")_
       println(greetHi("World"))
println(greetHello("World")) 

Output is:
Hi World
Hello World
 
 

Friday, April 6, 2018

Reducing code duplication using high order function

Scala provides various mechanisms for control abstraction. High-order function is one such way.

While in objected oriented languages,like Java, class inheritance is primary mechanism for avoiding code duplication, in functional programming languages,like Scala,writing higher-order functions is the preferred way of achieving same.

Higher-order functions are those functions which take functions as parameters. These functions enable us to create control abstractions which reduce code duplication in a major way.

Let's look into an example. Suppose you are writing a basic program which performs math operations on two input lists. We can start in a way used most commonly in non functional programming languages.

object BasicMathOperationsOnListPair {

  def add2Lists(intsX: List[Int],intsY: List[Int]) = {
    val sum = for ((x, y) <- (intsX zip intsY)) yield x + y
    sum
  }

  def multiply2Lists(intsX: List[Int],intsY: List[Int]) = {
    val mult = for ((x, y) <- (intsX zip intsY)) yield x * y
    mult
  }

  def subtract2Lists(intsX: List[Int],intsY: List[Int]) = {
    val subtract = for ((x, y) <- (intsX zip intsY)) yield x - y
    subtract
  }
}
Here, in every method we iterate through two input lists and apply appropriate math operations on the individual elements of the lists pairwise. But we are duplicating the iteration code in all the methods. Can we avoid this?Is it possible to factor out this repetitive code in a common method?

In functional programming languages higher order functions are every where, and we can make us of it to solve our problem. What we need to do is to write a function which contains iteration code and takes another function as input. This input function is then applied on the list elements pairwise during the looping. As can be seen from the nature of operations we are performing on the list elements, this input function should take two integer inputs and return an integer output. Let's write our higher order function.

def applyOpOnListsPairwise(intsX: List[Int], intsY: List[Int], op:(Int,Int) => Int) = {
  val result = for ((x, y) <- (intsX zip intsY)) yield op(x,y)
  result
}
Our higher order function here takes three parameters. First two are the integer lists to be operated upon pairwise. Third parameter,op, is of interest to us, and it is a function defined with signature as:

(Int,Int) => Int
So, now any function which meets this signature can be supplied as input to our higher order function.Let's now write our other functions to make use of our higher order function.

def add2ListsFPWay(intsX: List[Int],intsY: List[Int]) = {
  applyOpOnListsPairwise(intsX,intsY, (x:Int,y:Int) => x + y)
}

def multiply2ListsFPWay(intsX: List[Int],intsY: List[Int]) = {
  applyOpOnListsPairwise(intsX,intsY, (x:Int,y:Int) => x * y)
}

def subtract2ListsFPWay(intsX: List[Int],intsY: List[Int]) = {
  applyOpOnListsPairwise(intsX,intsY, (x:Int,y:Int) => x - y)
}
As can be seen, now our methods no more contain iteration code, which is now residing nicely and uniquely in 'applyOpOnListsPairwise'. We just structure our input function as per our need, and make sure that it meets the signature required for the input function of 'applyOpOnListsPairwise'.

Another advantage here is that we are making use of val. This brings immutability in our program. Similar program in a non-functional programming language would have made us to use mutable data structures.