You must have used switch cases many times in your Java code. However, the case entry can only be integer or any scalar type. What if the case entries become more flexible? When I say flexible, I mean it to be string, object, primitive data types or combination of all. The other way of doing this is to write a series of if-else-if statements which some times becomes annoying.

If something like this

object example1 extends App {
   def matchTest (x: Any): Any = x match {
      case 1 => "one"
      case "two" => 2
      case y: Int => "scala.Int"
   }
   println(matchTest("two"))
}

is a revolution for you, then Scala Pattern Matching is definitely a breath of fresh air!

Pattern Matching is a built in matching mechanism which matches data with first-match policy. Following is a simple snippet which will help you to understand this concept:

case class Person (name: String, gender: String, age: Int)

object example2 {
   def advance (xs: Person) = xs match {
      case Person (name, _, _)  => println(name)
      case _ => println(0)
   }

   def main (args: Array[String]) {
      val person = new Person("Edward", "male", 25)
      advance(person)
   }
}

It actually helps us to disintegrate a given object, binding it to the values of what it is composed of. This idea is not unique to Scala, but is also there in Haskell, OCaml and Erlang. We can write the above piece of code only because of the existence of something called “Extractors”.  Its functionality is somewhat opposite to that of constructor. While constructor creates an object from the given list of parameters, Extractors extracts the parameters from the constructed object. You can relate this with the line:

case Person (name, _, _)  => println(name)

Now the question is how does this actually works?

To make a note Scala library already contains some predefined extractors. In the above example we made use of “case” class which automatically creates a companion object that contains apply and unapply methods. The apply method is used to create new instance of the class whereas the unapply method needs to be implemented by an object in order for it to get extracted.

Given below is an example where we define our own unapply method. However, there can be more than one possible signature for unapply method but we will define the one which is commonly used:

trait Person {
   def name: String
   def gender: String
   def age: Int
}

class SeniorPerson(val name: String, val gender: String, val age: Int) extends Person

class JuniorPerson(val name: String, val gender: String, val age: Int) extends Person

object SeniorPerson {
   def unapply(user: SeniorPerson): Option[(String,String,Int)] = Some((user.name, user.gender, user.age))
}

object JuniorPerson {
   def unapply(user: JuniorPerson): Option[(String,String,Int)] = Some((user.name, user.gender, user.age))
}

object example3 {
   def main(args: Array[String]) {
      val user: Person = new JuniorPerson("Edward","male",10)
      user match {
         case SeniorPerson(name,_,age) => println("My name is " + name + ". My age is " + age)
         case JuniorPerson(name,_,age) => println("My name is " + name + ". My age is " + age)
         case _ => println(0)
      }
}


Hope this helps you to understand how the pattern matching actually works in Scala and helps you to implement your own extractors based on the usage. As for me it is one of the amazing alternative to IF statements!

By: Shweta Shaw

Share

Leave a Reply

Your email address will not be published. Required fields are marked *