Pattern Matching – Have A Look In Scala!

Knoldus Blog Audio
Reading Time: 5 minutes

What Is Pattern Matching?

When we talk about pattern matching , first thing that comes in our mind is a string matching or regular expression , but when it comes to functional programming this terminology takes a new meaning, which means that instead of string matching or regular expression matching , the functional programming is going to look into matching objects against other objects. Scala provides various techniques on the basis of which we can attain this pattern matching. Now we have further features such as pattern matching of types, pattern matching using switch, we have guards, we can match arrays, tuples, list etc., Though it would be a bit confusing as like how could we do all this? Don’t worry just have a look , i have covered almost each and every topic related to it.

Pattern Matching Using Better Switch

Well this is an application of pattern matching in scala. Here we provide multiple cases and match our value with those particular cases. Although it is bit same as of switch cases as we have in java but here we don’t have break statements, as well as we provide default statement with the help of (_=>) . And if we don’t provide this condition and if anything such as ( variable, value, type) etc,. would not match with any of the the condition then it throws a match error at that time. Here we simply create multiple cases and we can provide any type of string or integer etc., to match with the given condition, or what we can do is we can simple use variables it would simply assign the value of value of the variable defined at the beginning to the variable defined in the scope. For better understanding consider the screenshot added below.

val name = "Scala"

name match{

  case "Navneet" => println("Matched With Case One")

  case "Shubham" => println("Matched with Case two")

  case "Prashant And Gaurav" => println("Matched with case three")

  case _=> println("Not Matched")
}

As Here it will get matched with the case number three therefore it will simply print Matched!

Guards.

If we want to add qualifying logic to a case statement, Such as following a range of numbers, or matching a pattern, but only if that pattern matches some additional criteria. So For that Purpose We Use Guards , which can be better understood with the help of an example.

val number = 21

val r=number match {
  case first if 0 to 9 contains first => println("0-9 range: " + first)
  case second if 10 to 19 contains second => println("10-19 range: " + second)
  case third if 20 to 29 contains third => println("20-29 range: " + third)
  case _=> "Prashant"
}

println(r)

Variables In Pattern Matching

  • If the case keyword is followed by a variable name, then the match expression is assigned to that variable. For example:
// Assigning Match Expression with case Keyword
val number = 21
number match {
case result => println("The result is "+ result) // It will print 21
}
  • Here the value of variable number (Which is 21) , it will assigned to the variable defined after the case which is result , so here result will be assigned to a value which is 21.
  • After the value is assigned , it will simply execute the case , and The result is 21 will be printed.
  • Also there are few limitation which should be followed such as, Here variable patterns can conflict with constants, such as Pi. So for that we write it in lowercase as:-
import scala.math.Pi

val const: Double = 232
const match {
  case pi => "strange math? Pi = "+ pi
  case _ => "OK"
}
  • The constants which start in uppercase , we simply make the first letter in uppercase to use it as variable,  otherwise if we use it as in uppercase it will be treated as constant not variable. Apart from that for constant starting with lowercase we use back quotes to use them as constant, and if we use them as a lower case then in that case it will be treated as variable only. For example:-
import java.io.File.pathSeparator
val meth = "pathSeparatorOne"
meth match {
  case `pathSeparator` => println("strange math? pathSeparator = "+ `pathSeparator`)
  case _ => "OK"
}

Matching Arrays

We can match an array against its contents, with the help of pattern matching concept with arrays in scala. Here we simply provide an array and we match that array with the cases we provide. We achieve this by providing few cases, and matching with them. For Example:-

val arr= Array(1,2,3,4,5,6,7)
arr match {
  case Array(0) => "0"//
  case Array(x, y) => s"$x $y"//
  case Array(0, _*) => "0 ..."
  case _ => "something else"
}
  • Here , in our first case if the array will contain just 0 then this case will be executed.
  • In Second case, if there will be just element in the array say as(4,6) then this case will be executed.
  • If our array will contain 0 with the continuation of sequence , then this case will be executed.
  • Our fourth case will be executed if none of the cases will be matched.

Matching List

We can match an list against its contents, with the help of pattern matching concept with list in scala. Here we simply provide an list and we match that list with the cases we provide. We achieve this by providing few cases, and matching with them. For Example:-

val lst: List[Int] = List(1,2,3,5,5,3,34)
lst match {
  case 0 ::Nil=> "0"
  case x ::y::Nil=> s"$x $y"//
  case 0 ::tail=> "0..."
  case _ => "something else"
}
  • Here , in our first case if the list will contain just 0 then this case will be executed.
  • In Second case, if there will be just element in the list say as(4,6) then this case will be executed.
  • If our list will contain 0 with the continuation of sequence , then this case will be executed.
  • Our fourth case will be executed if none of the cases will be matched.

Matching Tuples

We can match an tuples against its contents, with the help of pattern matching concept with tuples in scala. Here we simply provide an tuples and we match that tuples with the cases we provide. We achieve this by providing few cases, and matching with them. For Example:-

val expr:Any = ("a" , "b" , 5)
expr match {

case (a, b,c) => println("matched "+ a + b + c)
case _ => println("Tuple Not Matched!")

}

Here , if our list would contain same number of elements/arguments, the case list has, then our first case will be executed otherwise the default case will be executed.

val pair= (0,8)
pair match {
  case (_, 0) | (0, _) => println("Matched Now") // OK, matches if _ is present
  case (x, 0) | (0, y) => println("Will not work") // Error, variables cannot bind with alternatives
  case _=> println("Not Matched Try Again")
}

In Scala, When we use alternatives, as shown above , then in that case we cannot bind variables. It will throw an error, so to overcome that we simply use (_).

Want To Explore More?

Want to Explore More About Pattern Matching In Scala , go through this- Pattern Matching In Scala!