
- Scala - Home
- Scala - Overview
- Scala - Features
- Scala - Environment Setup
- Scala - Build Tool (SBT)
- Scala - REPL
- Scala - Dot & Dotty
- Scala - Basic Syntax
- Scala - Hello World Program
- Scala - Identifiers
- Scala - Keywords
- Scala - Comments
- Scala - Code Blocks
- Scala - Semicolon
- Scala - Constructs
- Scala - Expressions
- Scala - Input and Output
- Scala - Optional Braces
- Scala - Underscore (_)
- Data Types and Variables
- Scala - Data Types
- Scala - Type Bounds
- Scala - Context Bound
- Scala - Variances
- Scala - Type Hierarchy
- Scala - Variables
- Scala - Variable Scopes
- Scala - Literals
- Scala - Numeric Types
- Scala - Boolean Types
- Scala - Char Type
- Scala - Unit Types
- Scala - Strings
- Scala - Arrays
- Scala - Null Type
- Scala - Nothing
- Scala - Any Type
- Scala - AnyRef Type
- Scala - Unified Types
- Scala - Dates and Times
- Scala - Ranges
- Scala - Multidimensional Arrays
- Scala - WrappedArray
- Scala - StringBuilder
- Scala - String Interpolation
- Scala - StringContext
- Scala - Type Casting
- Scala var vs val
- Scala Operators
- Scala - Operators
- Scala - Rules for Operators
- Scala - Arithmetic Operators
- Scala - Relational Operators
- Scala - Logical Operators
- Scala - Bitwise Operators
- Scala - Assignment Operators
- Scala - Operators Precedence
- Scala - Symbolic Operators
- Scala - Range Operator
- Scala - String Concatenation Operator
- Scala Conditional Statements
- Scala - IF ELSE
- Scala - IF-ELSE-IF-ELSE Statement
- Scala - Nested IF-ELSE Statement
- Scala Loop Statements
- Scala - Loop Statements
- Scala - while Loop
- Scala - do-while Loop
- Scala - Nested Loops
- Scala - for Loop
- Scala - break Statement
- Scala - yield Keyword
- Scala Classes & Objects
- Scala - Classes & Objects
- Scala - Constructors
- Scala - Auxiliary Constructor
- Scala - Primary Constructor
- Scala - This Keyword
- Scala - Nested Classes
- Scala - Getters and Setters
- Scala - Object Private Fields
- Scala - Singleton Object
- Scala - Companion Objects
- Scala - Creating Executable Programs
- Scala - Stateful Object
- Scala - Enumerations
- Scala - Polymorphism
- Scala - Access Modifiers
- Scala - Apply Method
- Scala - Update Methods
- Scala - UnapplySeq Method
- Scala - Inheritance
- Scala - Extending a Class
- Scala - Method Overloading
- Scala - Method Overriding
- Scala - Generic Classes
- Scala - Generic Functions
- Scala - Superclass Construction
- Scala Methods & Functions
- Scala - Methods
- Scala - Functions
- Scala - Methods vs Functions
- Scala - Main Methods
- Scala - Functions Call-by-Name
- Scala - Functions with Named Arguments
- Scala - Function with Variable Arguments
- Scala - Recursion Functions
- Scala - Default Parameter Values
- Scala - Functions without Parameters
- Scala - Implicit Parameters
- Scala - Higher-Order Functions
- Scala - Nested Functions
- Scala - Extension Methods
- Scala - Anonymous Functions
- Partially Applied Functions
- Scala - Lazy Val
- Scala - Pure Function
- Scala - Currying Functions
- Scala - Control Abstractions
- Scala - Corecursion
- Scala - Unfold
- Scala - Tail Recursion
- Scala - Infinite Sequences
- Scala - Dynamic Invocation
- Scala - Lambda Expressions
- Scala - Polymorphic Functions
- Scala Collections
- Scala - Collections
- Mutable and Immutable Collections
- Scala - Lists
- Scala - Sets
- Scala - Maps
- Scala - TreeMap
- Scala - SortedMap
- Scala - Tuples
- Scala - Iterators
- Scala - Options
- Scala - NumericRange
- Scala - Infinite Streams
- Scala - Parallel Collections
- Scala Advanced Types
- Scala - Union Types
- Scala - Intersection Types
- Scala - Type Aliases
- Scala - Structural Types
- Scala - Match Expression
- Scala - Singleton Type Operator
- Scala - Abstract Types
- Scala - Dependent Types
- Scala - Abstract Type Bounds
- Scala - Higher-Kinded Types
- Scala - Opaque Type Alias
- Scala - Path-Dependent Types
- Scala - Type Lambdas
- Scala - Type Inference
- Scala - Algebraic Data Types
- Scala Pattern Matching
- Scala - Pattern Matching
- Scala - Guards
- Scala - Variables in Patterns
- Scala - Type Patterns
- Scala - The Matchable Trait
- Scala - Matching Arrays
- Scala - Matching Lists
- Scala - Matching Tuples
- Scala - Exception Handling
- Scala - Extractors
- Scala - Pattern Bindings
- Scala - Regular Expressions
- Scala - Case Classes
- Scala - Partial Functions
- Scala - Packaging and Imports
- Scala - Implicit Imports
- Scala - Export Clauses
- Scala - Nested Packages
- Scala - Chained Packages
- Scala - Package Objects
- Scala Files I/O
- Scala - Files I/O
- Scala - Writing Files
- Scala - Listing Files
- Scala - Deleting Directories
- Scala - Check File Exists
- Scala Advanced Concepts
- Scala - Closures
- Scala - Futures
- Scala - Promises
- Scala - Traits
- Scala - Trait Mixins
- Scala - Layered Traits
- Scala - Trait Linearization
- Scala - Sealed Traits
- Scala - Transparent Traits
- Scala - Process Management
- Scala - Scaladoc
- Scala - Literal Type Arithmetic
- Scala - Inline keyword
- Scala - Def, Var & Val
- Scala - Dropped Features
- Scala Unit Testing
- Scala - Unit Testing
- Scala - uTest
- Scala - MUnit
- Scala - ScalaTest Runner
- Scala - ScalaMock
- Scala - JUnit
- Scala - Mocking
- Scala - BDD Testing
Scala - Pattern Matching
Pattern matching is the second most widely used feature of Scala, after function values and closures. Scala provides great support for pattern matching, in processing the messages.
A pattern match includes a sequence of alternatives, each starting with the keyword case. Each alternative includes a pattern and one or more expressions, which will be evaluated if the pattern matches. An arrow symbol => separates the pattern from the expressions.
Try the following example program, which shows how to match against an integer value.
Example
object Demo { def main(args: Array[String]) { println(matchTest(3)) } def matchTest(x: Int): String = x match { case 1 => "one" case 2 => "two" case _ => "many" } }
Save the above program in Demo.scala. The following commands are used to compile and execute this program.
Command
\>scalac Demo.scala \>scala Demo
Output
many
The block with the case statements defines a function, which maps integers to strings. The match keyword provides a convenient way of applying a function (like the pattern matching function above) to an object.
Try the following example program, which matches a value against patterns of different types.
Example
object Demo { def main(args: Array[String]) { println(matchTest("two")) println(matchTest("test")) println(matchTest(1)) } def matchTest(x: Any): Any = x match { case 1 => "one" case "two" => 2 case y: Int => "scala.Int" case _ => "many" } }
Save the above program in Demo.scala. The following commands are used to compile and execute this program.
Command
\>scalac Demo.scala \>scala Demo
Output
2 many one
Matching using Case Classes
The case classes are special classes that are used in pattern matching with case expressions. Syntactically, these are standard classes with a special modifier: case.
Try the following, it is a simple pattern matching example using case class.
Example
object Demo { def main(args: Array[String]) { val alice = new Person("Alice", 25) val bob = new Person("Bob", 32) val charlie = new Person("Charlie", 32) for (person <- List(alice, bob, charlie)) { person match { case Person("Alice", 25) => println("Hi Alice!") case Person("Bob", 32) => println("Hi Bob!") case Person(name, age) => println( "Age: " + age + " year, name: " + name + "?") } } } case class Person(name: String, age: Int) }
Save the above program in Demo.scala. The following commands are used to compile and execute this program.
Command
\>scalac Demo.scala \>scala Demo
Output
Hi Alice! Hi Bob! Age: 32 year, name: Charlie?
Adding the case keyword causes the compiler to add a number of useful features automatically. The keyword suggests an association with case expressions in pattern matching.
First, the compiler automatically converts the constructor arguments into immutable fields (vals). The val keyword is optional. If you want mutable fields, use the var keyword. So, our constructor argument lists are now shorter.
Second, the compiler automatically implements equals, hashCode, and toString methods to the class, which use the fields specified as constructor arguments. So, we no longer need our own toString() methods.
Finally, also, the body of Person class becomes empty because there are no methods that we need to define!
Pattern Matching with Sealed Traits
Sealed traits ensure that all implementations of the trait are known at compile-time. So pattern matching is more exhaustive and safer. Using sealed traits can help the compiler check for missing cases in pattern matching.
Example
sealed trait Animal case class Dog(name: String) extends Animal case class Cat(name: String) extends Animal case object Parrot extends Animal object Demo { def main(args: Array[String]) = { val animals: List[Animal] = List(Dog("Rex"), Cat("Whiskers"), Parrot) animals.foreach { case Dog(name) => println(s"Dog: $name") case Cat(name) => println(s"Cat: $name") case Parrot => println("Parrot") } } }
Save the above program in Demo.scala. Use the following commands to compile and execute this program.
Command
> scalac Demo.scala > scala Demo
Output
Dog: Rex Cat: Whiskers Parrot
Pattern Matching with Option
Option is a container type that represents optional values. Pattern matching is used to handle Option values. So, it is easy to work with missing values.
Try following example of pattern matching with Option -
Example
object Demo { def main(args: Array[String]) = { val someValue: Option[Int] = Some(42) val noneValue: Option[Int] = None println(showOption(someValue)) println(showOption(noneValue)) } def showOption(opt: Option[Int]): String = opt match { case Some(value) => s"The value is $value" case None => "No value" } }
Save the above program in Demo.scala. Use the following commands to compile and execute this program.
Command
> scalac Demo.scala > scala Demo
Output
The value is 42 No value
Pattern Matching with Tuples
Tuples group multiple values into a single compound value. Pattern matching can be used to decompose tuples into their constituent parts.
Try following example of pattern matching with tuple -
Example
object Demo { def main(args: Array[String]) = { val tuple = (1, "Scala", true) tuple match { case (a, b, c) => println(s"Int: $a, String: $b, Boolean: $c") } } }
Save the above program in Demo.scala. Use the following commands to compile and execute this program.
Command
> scalac Demo.scala > scala Demo
Output
Int: 1, String: Scala, Boolean: true
Pattern Matching with Lists
Pattern matching is a powerful way to process lists for handling different list structures.
Try following example of pattern matching with list -
Example
object Demo { def main(args: Array[String]) = { val list = List(1, 2, 3, 4) list match { case Nil => println("Empty list") case head :: tail => println(s"Head: $head, Tail: $tail") } } }
Save the above program in Demo.scala. Use the following commands to compile and execute this program.
Command
> scalac Demo.scala > scala Demo
Output
Head: 1, Tail: List(2, 3, 4)
Pattern Matching Summary
- Pattern matching is a powerful feature in Scala. Pattern matching is used extensively for handling various data structures and types.
- Case classes and sealed traits enhance pattern matching by making the code more readable and type-safe.
- Pattern matching with Option, tuples, and lists provides elegant solutions for handling common data structures.