
- 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 - Partial Functions
You can define functions that are not necessarily defined for all possible input values. Partial functions can be used to handle cases where a function can only be applied to a subset of possible inputs.
Partial Functions
Partial function is an instance of the PartialFunction trait. This trait defines methods for checking whether a function is defined at a given input. It is also used for applying the function to that input.
Understanding Partial Functions
Let us take an example of a partial function that handles division, but only for non-zero divisors. The isDefinedAt method checks if the divisor is non-zero. The apply method performs the division.
The isDefinedAt method is what makes a function partial. It checks if a given input satisfies the conditions for which the function is defined. If the condition is met, the function can be applied to the input.
The apply method is used to apply the function to the input if the conditions are met. If the conditions are not met and the function is applied, it will throw a MatchError.
In this example, we will define a partial function called divide that divides two integers only if the divisor is not zero.
Syntax
val divide: PartialFunction[(Int, Int), Int] = { case (num, den) if den != 0 => num / den }
In this example, the partial function divide is defined for all pairs (num, den) where den is not zero. If the divisor den is zero, the function is not defined.
Example
Following example program shows a partial function for division -
object Demo { def main(args: Array[String]) = { val divide: PartialFunction[(Int, Int), Int] = { case (num, den) if den != 0 => num / den } val pairs = List((6, 3), (4, 0), (9, 3)) pairs.foreach { pair => if (divide.isDefinedAt(pair)) { println(s"Result of ${pair._1} / ${pair._2} is ${divide(pair)}") } else { println(s"Cannot divide ${pair._1} by ${pair._2}") } } } }
Save the above program in Demo.scala. Use the following commands to compile and execute this program.
Command
> scalac Demo.scala > scala Demo
Output
Result of 6 / 3 is 2 Cannot divide 4 by 0 Result of 9 / 3 is 3
Chaining Partial Functions
You can chain partial functions together using the orElse method. So you can create a composite function that handles multiple cases.
Example
Consider a partial function that handles different types of input values and chains them together.
Let us take an example of chaining partial functions to handle multiple cases. We will define three partial functions: intHandler, stringHandler, and doubleHandler. Each function handles a different type of input.
The intHandler handles integers, the stringHandler handles strings, and the doubleHandler handles doubles. We will then chain these partial functions using the orElse method to create a composite function called handler.
Syntax
val intHandler: PartialFunction[Any, String] = { case i: Int => s"Int: $i" } val stringHandler: PartialFunction[Any, String] = { case s: String => s"String: $s" } val doubleHandler: PartialFunction[Any, String] = { case d: Double => s"Double: $d" } val handler = intHandler orElse stringHandler orElse doubleHandler
Example
Following example program shows chaining partial functions to handle multiple cases -
object Demo { def main(args: Array[String]) = { val intHandler: PartialFunction[Any, String] = { case i: Int => s"Int: $i" } val stringHandler: PartialFunction[Any, String] = { case s: String => s"String: $s" } val doubleHandler: PartialFunction[Any, String] = { case d: Double => s"Double: $d" } val handler = intHandler orElse stringHandler orElse doubleHandler val inputs = List(42, "Scala", 3.14, true) inputs.foreach { input => if (handler.isDefinedAt(input)) { println(handler(input)) } else { println(s"Unhandled input: $input") } } } }
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: 42 String: Scala Double: 3.14 Unhandled input: true
In this example, the partial functions intHandler, stringHandler, and doubleHandler are chained together to handle different types of input values. The composite function handler is then used to process a list of inputs. So it can handle for integers, strings, and doubles, and default case of other types.
Combining Partial Functions with collect
The collect method is for applying partial functions to collections. You can filter and transform elements in a collection using a partial function.
Example
There is list of mixed values. You also have partial function that extracts integers and doubles from the list.
Let us take example of using the collect method to apply partial function to collection. We will define this partial function that called extractNumbers. It extracts integers and doubles from a list of mixed values.
The extractNumbers partial function converts integers to doubles. It keeps doubles as these are. The collect method will then apply the partial function to the list. So there will be a new list containing only the extracted numbers.
Syntax
val extractNumbers: PartialFunction[Any, Double] = { case i: Int => i.toDouble case d: Double => d }
Following example program shows how to use the collect method with a partial function to extract numbers from a list -
Example
object Demo { def main(args: Array[String]) = { val values = List(1, "Scala", 2.5, 3, "Java", 4.0) val extractNumbers: PartialFunction[Any, Double] = { case i: Int => i.toDouble case d: Double => d } val numbers = values.collect(extractNumbers) println(s"Extracted numbers: $numbers") } }
Save the above program in Demo.scala. Use the following commands to compile and execute this program.
Command
> scalac Demo.scala > scala Demo
Output
Extracted numbers: List(1.0, 2.5, 3.0, 4.0)
In this example, the extractNumbers partial function extracts integers and doubles from the values list. It converts integers to doubles. The collect method applies the partial function to the list. So, there will be a new list containing only the extracted numbers.
Partial Functions Summary
- You can define partial functions using the PartialFunction It includes the isDefinedAt and apply methods.
- The isDefinedAt method checks if a function is defined for a given input. Whereas the apply method applies the function to the input.
- You can define partial functions using the case syntax to specify the inputs for which these are defined.
- You can chain partial functions using the orElse method to create composite functions that handle multiple cases.
- You can filter and transform collections using partial functions.
- You can handle various vases in a concise and expressive manner using partial functions.