
- 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 with Variables and Custom Types
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. One aspect of pattern matching is to use variables within patterns. It can bind to values for more expressive code.
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.
Pattern Matching for Variables
Pattern matching can be used to test strings and variables against patterns. These return different results based on the match outcome. The syntax for matching a string and variable -
def typedPatternMatching(any: Any): String = { any match { case string: String => s"I am a string. My value: $string" case integer: Int => s"I am an integer. My value: $integer" case _ => s"I am from an unknown type. My value: $any" } }
This function takes the argument of type Any and matches it against different types. It returns a string that describes the matched type and its value.
Example
def typedPatternMatching(any: Any): String = { any match { case string: String => s"I am a string. My value: $string" case integer: Int => s"I am an integer. My value: $integer" case _ => s"I am from an unknown type. My value: $any" } } object Demo { def main(args: Array[String]): Unit = { val mixedList: List[Any] = List(42, "Scala", 3.14) mixedList.foreach { element => println(typedPatternMatching(element)) } } }
Save the above program in Demo.scala. Use the following commands to compile and execute this program.
Command
> scalac Demo.scala > scala Demo
Output
I am an integer. My value: 42 I am a string. My value: Scala I am from an unknown type. My value: 3.14
We pass each element in mixedList to typedPatternMatching function. It matches the element against different types and prints the result.
Stable Identifiers in Pattern Matching
In some cases, you may want to match against a specific value stored in a variable. But, using the variable name in a pattern will bind the variable to the matched value rather than compare against the stored value. You can use stable identifiers to get desired behavior. Stable identifiers must either start with an uppercase letter or be surrounded by backticks.
Example
def mMatch(s: String) = { val target: String = "a" s match { case `target` => println(s"It was $target") case _ => println("It was something else") } } def mMatch2(s: String) = { val Target: String = "a" s match { case Target => println(s"It was $Target") case _ => println("It was something else") } }
Here, starting the variable name with a capital letter for the pattern matches the specific value stored in the variable.
Variable Binding in Pattern Matching
When a pattern matches a value, variables in the pattern are bound to corresponding parts of the value.
Example
Following is the example which shows you how to variable binding in pattern matching –
object Demo { def main(args: Array[String]): Unit = { val maybeValue: Option[Int] = Some(42) maybeValue match { case Some(value) => println(s"Value is: $value") case None => println("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
Value is: 42
Here, the maybeValue variable is matched against the Some and None cases of the Option type, with the value variable binding to the contained integer.
Pattern Matching with Custom Types
You can extend pattern matching to work with custom types and classes. So, you can decompose instances and access their fields directly.
Example
Following is the example which shows you how to use pattern matching with custom type -
sealed trait Shape case class Circle(radius: Double) extends Shape case class Rectangle(width: Double, height: Double) extends Shape object Demo { def main(args: Array[String]): Unit = { val shape: Shape = Circle(5.0) shape match { case Circle(r) => println(s"Circle with radius: $r") case Rectangle(w, h) => println(s"Rectangle with width: $w and height: $h") case _ => println("Unknown shape") } } }
Save the above program in Demo.scala. Use the following commands to compile and execute this program.
Command
> scalac Demo.scala > scala Demo
Output
Circle with radius: 5.0
In this example, the shape variable is matched against different case classes. With the variables r, w, and h binding to the respective fields of Circle and Rectangle.
Pattern Matching with Variables Summary
- Pattern matching is used to test values and decompose into constituent parts using patterns.
- You can match stable identifiers against specific values stored in variables.
- Variable binding in patterns extract and work with parts of matched values.
- You can use pattern matching with custom types to access fields and decompose instances.
- Typed pattern matching simplifies type handling and improves code readability.