Do you think IIT Guwahati certified course can help you in your career?
No
Introduction
Hello Ninjas, Today we are going to learn Scala Pattern Matching; we will see the example and implementation for the same. Pattern Matching is the most widely used feature in Scala. We will look into the different cases of Pattern Matching, like constants, sequences, constructors, classes, etc.
Before moving forward, let’s understand Pattern Matching.
Pattern Matching
Pattern Matching is used to check the sequence of tokens if it contains a specific pattern or not. It works the same way as the switch statement in C and Java. Instead of the switch statement, the match keyword is used.
Scala pattern matching is made of variables, constants, constructors, type tests, etc. It is defined in the root class of Scala so that it’s available to all the objects. It can contain alternatives, with each alternative starting from the case keyword that further includes a pattern and expressions separated by an arrow symbol ( => ), which will be evaluated if the pattern gets matched.
We aim to match one or more patterns like variable patterns, constant patterns, sequence patterns, constructor patterns, tuple, or type patterns. Let’s begin by first learning the syntax of match expression.
Syntax
We will discuss one by one the multiple parts of the match expression. Let’s look at this example to understand this:
def patternMatchingSyntax(candidate: String): Int = {
candidate match {
case "Zero" => 0
case "One" => 1
case _ => -1
}
}
First, we have a value that we use to match with the patterns; it is called a candidate.
Next, we have a keyword match, which is used to person pattern matching.
Multiple case sequences, consisting of the case keyword, which includes a pattern and expressions separated by an arrow symbol ( => ), will be evaluated if the pattern is matched.
Last, a default clause will get executed if no other pattern matches. It is recognized by an underscore (_) at the end of case clauses.
Patterns in Match Expression
Now, we are fully familiar with the syntax, and we can start with the different cases of pattern matching. There are many types of patterns like variable patterns, constant patterns, sequence patterns, constructor patterns, tuples, or type patterns, so let's start one by one:
Constants
A constant pattern is used to match numbers or boolean values. It can only match itself. Any literal can be used as a constant. We need to specify the literal; for example, if we specify 1 as the literal, it can only map the Int value of 1.
Example
object CodingNinjas {
def main(args: Array[String]) {
println(constantPattern(1.5d));
}
def constantPattern(constant: Any): String = {
constant match {
case 0 => "Zero"
case 1.2d => "Double value"
case false => "False Value"
case _ => s"I'm unknown and equal to $constant"
}
}
}
The output of the following code is displayed below:
Classes
Case classes are used to extend a common abstract class. It helps us to combine pattern matching with the power of inheritance. In this expression, the match keyword is used to evaluate the reference of the abstract class in pattern matching.
Example
object CodingNinjas {
abstract class Animal
case class Mammal(name: String, Land: Boolean) extends Animal
case class Bird(name: String) extends Animal
def main(args: Array[String]) {
val someBird = Bird("Laysan")
println(caseClassesPatternMatching(someBird));
}
def caseClassesPatternMatching(animal: Animal): String = {
animal match {
case Mammal(name, fromSea) => s"I'm a $name, a kind of mammal. Am I from the sea? $fromSea"
case Bird(name) => s"I'm a $name, a kind of bird"
case _ => "I'm an unknown animal"
}
}
}
This example will generate the following output. An object of bird class has been matched.
Sequences
The sequences in Scala are arrays, lists, and vectors. Their elements also form patterns and can be matched. We can match against these sequences. To match “zero or more elements” whose count is unknown, use ( _*),and to match a single element, use ( _ ).
Example
object CodingNinjas {
def main(args: Array[String]) {
println(sequencesPatternMatching((1,2,3)));
}
def sequencesPatternMatching(sequence: Any): String = {
sequence match {
case List(singleElement) => s"List with single element: $singleElement"
case List(_, _*) => s"List with one or multiple elements: sequence"
case Vector(1, 2, _*) => s"Vector: $sequence"
case _ => s"This is an unrecognized sequence with value: $sequence"
}
}
}
The output in this example will generate the default case:
Tuples
Tuples contain a fixed number of sub-objects. It is of limited size and consists of mixed elements. The format for the tuple pattern is (p1,...,pn).
Example
object CodingNinjas {
def main(args: Array[String]) {
println(tuplesPattern((1,2)));
}
def tuplesPattern(tuple: Any): String = {
tuple match {
case (first, second) => s"Tuple with two elements: $first & $second"
case (first, second, third) => s"Tuple with three elements: $first & $second & $third"
case _ => s"Unrecognized pattern with value: $tuple"
}
}
}
The above example was used to match against two elements 1&2. Output for the same is attached below.
Typed Patterns
In scala, each object is of the static type, which cannot be changed. Hence it is a typed language. For example, Only a boolean expression can be found inside a boolean object.
Example
object CodingNinjas {
def main(args: Array[String]) {
println(typedPattern(("Hello")));
}
def typedPattern(any: Any): String = {
any match {
case string: String => s"A string with value: $string"
case integer: Int => s"An integer with value: $integer"
case _ => s"Unknown type with value: $any"
}
}
}
A string (“Hello”) is matched in the above example as a String is a typed pattern. Hence it will be compared with the case string, as shown in the output below.
Regex Patterns
In Scala, Regular expressions provide a common pattern used to match a series of input data. We can use them in Pattern Matching. They are also termed Scala Regex.
Example
object CodingNinjas {
def main(args: Array[String]) {
println(regexPatterns(("123")));
}
def regexPatterns(toMatch: String): String = {
val numeric = """([0-9]+)""".r
val alphabetic = """([a-zA-Z]+)""".r
val alphanumeric = """([a-zA-Z0-9]+)""".r
toMatch match {
case numeric(value) => s"Numeric with value $value"
case alphabetic(value) => s"Alphabetic with value $value"
case alphanumeric(value) => s"Alphanumeric with value $value"
case _ => s"Characters other than alphanumerics, and value $toMatch"
}
}
}
The input provided was “123”, which is matched with numeric. Output for the same is shown below.
Apart from these patterns, we can also make sure if a specific condition is being fulfilled with Scala Pattern Guards; let’s discuss this in brief.
We can combine if expressions with cases in scala to power the pattern matching; this is done with the Scala Pattern Guards. We can use them to customize the patterns with the help of some specific conditions. These are the boolean expressions that are used on the same level as the case clause.
Example
object CodingNinjas {
def patternGuardsExample(i: Int): String = {
I match {
case a if a < 0 => s"$a is a negative number"
case b if b > 0 => s"$b is a positive number"
case c => s"$c neither positive nor negative"
}
}
def main(args: Array[String]) {
print(patternGuardsExample(-19));
}
}
In the example snippet of code, we have used the if expression with case to check if a number is positive or negative. We have given -19 as input. Hence it executes case a and returns the following output.
Frequently asked questions
What is Scala?
Scala is a general-purpose programming language that incorporates concepts of both object-oriented and functional programming. It is a very logical, concise, and extraordinarily powerful language.
What is Scala Pattern Matching?
Scala Pattern Matching is a method of checking a value against some pattern. It provides more readable and concise code with the ability to match against complex patterns.
What are the different types of patterns in Scala Pattern Matching?
Scala Pattern Matching is used to match different patterns like constant & variable patterns, typed, literal, class, constructor, tuples, etc.
Can we provide custom conditions with Scala Pattern Matching?
Yes, we can make sure if a specific condition is being followed with the case. To implement this, we have pattern guards. We can combine the if expression with the case statement.
What are the Sequences and how pattern matching is done?
Arrays, lists, and vectors are sequences in Scala. Their elements can be matched for the pattern. To match “zero or more elements” whose count is unknown, use ( _*),and to match a single element, use ( _ ).
Conclusion
In this article, We have learned about Scala Pattern Matching. We have seen various patterns that can be matched against any expression. At last, we have discussed Scala pattern guards with an example.
You can check out our other articles if you want to learn more in Scala -