When we want to perform different computations based on some match or condition then we use pattern matching.
If you are familiar with switch statements, then this is similar to that but is a little more powerful.
There are different types of pattern matching techniques:
1. Wildcard Pattern
Wildcard pattern is referred to as the condition which is executed if all else fails. This is usually marked using “_” (underscore symbol).
val list = List("One", "Two", "Three")
list match {
case Nil => "Star Pattern"
case _ => "Wild card Pattern"
}
Output:
val list: List[String] = List(One, Two, Three)
val res0: String = Wild card Pattern
2. Variable Pattern
val message = "Hello ! What's up "
message match {
case greet: String => s"$greet TGB Users"
}
Output:
val message: String = "Hello ! What's up "
val res1: String = Hello ! What's up TGB Users
3. Constant Pattern
val ONE: Int = 1
val TWO: Int = 2
val THREE: Int = 3
def matcher(x: Int) {
x match {
case ONE => println("one")
case TWO => println("two")
case THREE => println("three")
case _ => println("many : Match case for Wildcard Pattern")
}
}
matcher(ONE)
matcher(TWO)
Output:
val ONE: Int = 1
val TWO: Int = 2
val THREE: Int = 3
def matcher(x: Int): Unit
one
two
4. Constructor Pattern
case class Pet(name: String, animal: String)
val listOfPets = List(Pet("Ginger", "Dog"),
Pet("boo", "Cat"),
Pet("Tommy", "Dog"),
Pet("Bow", "Dog"))
listOfPets.map {
case Pet(name, "Dog") => s"$name is a Dog"
case _ => "The pet is not a Dog :)"
}
Output:
class Person
class Pet
val listOfPets: List[Pet] = List(Pet(Ginger,Dog), Pet(boo,Cat), Pet(Tommy,Dog), Pet(Bow,Dog))
val res4: List[String] = List(Ginger is a Dog, The pet is not a Dog :), Tommy is a Dog, Bow is a Dog)
5. Sequence Pattern
def getListType(x: List[Any]) = {
x match {
case Nil => "Got an Empty List"
case List(10, _, _) => "Got a size three list, starting with 10"
case List(1, _*) => "Got a list starting with one"
case _ => "Fallen in default case"
}
}
getListType(List())
getListType(List(1, 2, 3))
getListType(List(10, 2, 0))
getListType(List(3, 4, 7, 1))
Output:
def getListType(x: List[Any]): String
val res5: String = Got an Empty List
val res6: String = Got a list starting with one
val res7: String = Got a size three list, starting with 10
val res8: String = Fallen in default case
6. Tuple Pattern
val zippedValue1 = ("Gaurav", 1, 25)
val zippedValue2 = ("Mohit", 1, "25")
def decode(details: Any) = {
details match {
case (name: String, sr: Int, age: Int) => s"$name-------$sr-------$age"
case (name: String, sr: Int, age: String) => s"$name--------$sr"
}
}
decode(zippedValue1)
decode(zippedValue2)
Output:
val zippedValue1: (String, Int, Int) = (Gaurav,1,25)
val zippedValue2: (String, Int, String) = (Mohit,1,25)
def decode(details: Any): String
val res9: String = Gaurav-------1-------25
val res10: String = Mohit--------1
7. Typed Pattern
def returnWhatYouGet(valType: Any) = {
valType match {
case s: String => s"you gave me this string: $s"
case i: Int => s"thanks for the int: $i"
case f: Float => s"thanks for the float: $f"
case a: Array[Int] => s"an array of int: ${ a.mkString(",") }"
case as: Array[String] => s"an array of strings: ${ as.mkString(",") }"
case d: Pet => s"dog: ${ d.name }"
case list: List[_] => s"thanks for the List: $list"
case m: Map[_, _] => m.toString
}
}
returnWhatYouGet("Hi")
returnWhatYouGet(1)
returnWhatYouGet(listOfPets.head)
Output:
def returnWhatYouGet(valType: Any): String
val res11: String = you gave me this string: Hi
val res12: String = thanks for the int: 1
val res13: String = dog: Ginger
8. Using Pattern Guard
abstract class Notification
case class Email(sender:String, title: String, body: String) extends Notification
case class SMS(caller: String, message: String) extends Notification
case class VoiceRecording(contactName: String, link: String) extends Notification
def showImportantNotification(notification: Notification, importantPeopleInfo: Seq[String]): String = {
notification match {
case Email(email, _, _) if importantPeopleInfo.contains(email) =>
"You got an email from special someone!"
case SMS(number, _) if importantPeopleInfo.contains(number) =>
"You got an SMS from special someone!"
case other => "Unknown Service"
// nothing special, delegate to our original showNotification function
}
}
val importantPeopleInfo = Seq("867-5309", "jenny@gmail.com")
val someSms = SMS("867-5309", "Are you there?")
val someVoiceRecording = VoiceRecording("Tom", "voicerecording.org/id/123")
val importantEmail = Email("jenny@gmail.com", "Drinks tonight?", "I'm free after 5!")
val importantSms = SMS("867-5309", "I'm here! Where are you?")
println(showImportantNotification(someSms, importantPeopleInfo))
println(showImportantNotification(someVoiceRecording, importantPeopleInfo))
println(showImportantNotification(importantEmail, importantPeopleInfo))
println(showImportantNotification(importantSms, importantPeopleInfo))
Output:
class Notification
class Email
class SMS
class VoiceRecording
def showImportantNotification(notification: Notification, importantPeopleInfo: Seq[String]): String
val importantPeopleInfo: Seq[String] = List(867-5309, jenny@gmail.com)
val someSms: SMS = SMS(867-5309,Are you there?)
val someVoiceRecording: VoiceRecording = VoiceRecording(Tom,voicerecording.org/id/123)
val importantEmail: Email = Email(jenny@gmail.com,Drinks tonight?,I'm free after 5!)
val importantSms: SMS = SMS(867-5309,I'm here! Where are you?)
You got an SMS from special someone!
Unknown Service
You got an email from special someone!
You got an SMS from special someone!
9. Sealed Class pattern
sealed abstract class Furniture
case class Couch() extends Furniture
case class Chair() extends Furniture
def findPlaceToSit(piece: Furniture): String = piece match {
case a: Couch => "Lie on the couch"
case b: Chair => "Sit on the chair"
}
Output:
class Furniture
class Couch
class Chair
def findPlaceToSit(piece: Furniture): String