Pattern matching and Recursion in Scala

People coming from Java background , might have used switch case as a means to implement strategy pattern , or just for routing to a different workflow based on some flag value. Scala provides pattern matching on different types which fits into multiple scenarios. In this blog we will see how pattern matching can be leveraged to perform operations on a List using recursion.

Java switch case vs Scala pattern matching

In the below code, you can see a sample code for switch case to get the salary of employee with some side effects (obviously ;))

public int getSalary(int payCode) {
switch (payCode){
case 1 : emp.setEmployeeType(Type.ENGINEER)
break;
case 2 : emp.setEmployeeType(EmpType.TEAMLEAD)
break;
case 3 : emp.setEmployeeType(Type.ARCHITECT)
break;
default: emp.setEmployeeType(Type.DEFAULT)
break;
}
return calculateSalary(emp);
}

Here’s how we can reimplement the same in scala with pattern matching

def getSalary(payCode : Int) = payCode match {
case 1 => calculateSalary(emp.setEmployeeType(Type.ENGINEER))
case 2 => calculateSalary(emp.setEmployeeType(Type.TEAMLEAD))
case 3 => calculateSalary(emp.setEmployeeType(Type.ARCHITECT)) case _ => calculateSalary(emp.setEmployeeType(Type.DEFAULT))
}

Now that you have seen how switch case in java, maps to pattern matching in scala, let’s dive into using scala for performing operations on List .

Step 1. Create a list trait and the implement in case class

sealed trait MyList
case class Cons(head: Int,tail : MyList) extends MyList
case object Nil extends MyList

The above code demonstrates a simple trait which we have extended to in Cons class to provide a structure in the form of head and tail of a List. Now we will be creating a companion object which can be used to instantiate the List object in REPL.

Step 2. Create companion object

object MyList{
def apply(as : Int*):MyList = {
if(as.isEmpty) Nil else Cons(as.head,apply(as.tail:_*))
}
}

Step 3. Add a method in trait to sum all the numbers present in the List
 Now that we have a List, we would want to write functions as part of the trait which will be invoked on the List object. Here’s a sumAll method which provides a summation of all the Integers present in the list.

def sumAll:Int = this match {
case Cons(h,t) => h + t.sumAll
case Nil => 0
}

The above code triggers the sumAll method on this, which refers to the current List object. The first case will do a pattern match on head and tail of the Cons data constructor and if the match found then it takes the head and recursively calls the sumAll method on the remaining tail which is also a List object. If there is no match which is the default case then 0 is returned.

Another ProductAll method in trait

def productAll : Int = this match{
case Cons(h,t) => h * t.productAll
case Nil => 1
}

Below is the complete code snippet.

Originally published at shadamez.wordpress.com on May 13, 2015.

One clap, two clap, three clap, forty?

By clapping more or less, you can signal to us which stories really stand out.