Wednesday, 14 September 2016

Scala Partial Functions In Depth

Post Brief Table of Content

  • Introduction
  • What is Partial Function?
  • Partial Function General Example
  • PartialFunction in Scala API
  • Partial Function Examples
  • Partial Function Rules
  • Partial Function Real-Time Scenarios
  • Scala Partial Functions Interview Questions

Introduction

Before reading this post, please go through my previous Scala posts to learn some Scala Basics. In this post, I'm going to discuss one interesting concept: Scala Partial Functions.

Scala Language has many kinds of functions. Partial Function is one of the types of Functions available in Scala Language. To read about functions basics, please click here: Scala Functions Basics

What is Partial Function?

If a function does NOT support all argument(s) of it's input(s), then that function is known as a Partial Function. Opposite to Partial Function is Total Function which supports all argument(s) of it's input(s).

Partial Functions are defined only partially, which does not support all possible input(s). It supports only subset of it's input(s).

In Scala, we can use scala.PartialFunction trait to define Partial Functions. We will discuss how to define it with some examples in the coming sections.


Partial Function General Example

In this section, we will take one Real-time Example to explain this Partial Function concept.

I think, everyone did some Mathematics from Schooling days.  In Maths, division operation does not support for all inputs. It is NOT defined for denominator = 0. Hence, division is a partial function.

In a/b, if b=0 we will get ArthimeticException 
scala> 1/0
java.lang.ArithmeticException: / by zero
Here nominator = 1 and denominator = 0. Hence we got exception.

Scala Function Example:-
scala> def division(no1:Int, no2:Int) = no1/no2
division: (no1: Int, no2: Int)Int

scala> division(1,1)
res9: Int = 1

scala> division(1,0)
java.lang.ArithmeticException: / by zero

scala> division(0,1)
res11: Int = 0

scala> division(0,0)
java.lang.ArithmeticException: / by zero

PartialFunction In Scala API

Scala has built-in support to define Partial functions. We can use scala.PartialFunction trait to define Partial Functions.

Let us explore scala.PartialFunction trait now. In Scala API, it is define as shown below:

package scala
trait PartialFunction[-A, +B] extends (A) ⇒ B
In simple way, it is defined as PartialFunction[A,B]
  • A is input to this function
  • B is output to this function
It has couple of functions. "isDefinedAt" is more popular and useful function. We will discuss about this function usage in the Examples section.

Partial Function Examples

Let us explore PartilaFunction with some examples here.

Example-1:-
scala> val increment: PartialFunction[Int, Int] = {
     |  case x:Int => x+1
     | }
increment: PartialFunction[Int,Int] = <function1>

scala> increment(10)
res22: Int = 11

Here both input and output are of same type: Int.

Example-2:-
Now let us define our division function (defined "Partial Function Real-time Example" section) using PartialFunction

scala> val division: PartialFunction[(Int,Int), Int] = {
     |  case (n:Int,d:Int) if d!= 0 => n/d
     | }
division: PartialFunction[(Int, Int),Int] = <function1>

scala> division(1,1)
res23: Int = 1

scala> division(1,0)
scala.MatchError: (1,0) (of class scala.Tuple2$mcII$sp)

scala> division(0,1)
res25: Int = 0

scala> division(0,0)
scala.MatchError: (0,0) (of class scala.Tuple2$mcII$sp)

Here input is a Tuple2 of (Int,Int) type and output is of Int type.

Example-3:-

scala> val greet: PartialFunction[String, Unit] = 
       { case name:String => println("Hello, "+ name) }
greet: PartialFunction[String,Unit] = <function1>

scala> greet("Rams")
Hello, Rams

A Partial Function can return Unit (no return value) also.

Partial Function Rules


In Scala Language, we should follow some rules to define Partial Functions:
  • Use scala.PartialFunction trait to define partial functions
  • "case" block(s) are used to define partial function's body
  • Entire function should be enclosed in curly braces

scala> val increment: PartialFunction[Int, Int] = case x:Int => x+1
<console>:1: error: illegal start of simple expression
val increment: PartialFunction[Int, Int] = case x:Int => x+1

Here we are using same increment function but without curly braces.
  • We can use "isDefinedAt" to check whether a Partial Function is defined at given input

if(division.isDefinedAt(1,0))
// Do something
else
// Do something else


NOTE:-
If input does NOT any available cases in a Partial Function, it throws MatchError as shown below:
scala> val division: PartialFunction[(Int,Int), Int] = {
     |  case (n:Int,d:Int) if d!= 0 => n/d
     | }
division: PartialFunction[(Int, Int),Int] = <function1>

scala> division(0,0)
scala.MatchError: (0,0) (of class scala.Tuple2$mcII$sp)
Partial Function Real-time Scenarios
We have already discussed some useful examples in above sections. However, I want to discuss some real-time scenarios in this section

Scenario-1:- 

One of the best examples is Akka Actors
def receive {

  case ... => Do some thing
}
In developing Actors, we should define the implementation of a receive function as shown in the above example. It is actual a Partial Function

def receive: PartialFunction[Any,Unit] = { ... }
Scenario-2:- 

Scala API uses Partial Function concept in many places. For instance, collect function available in Collection API.


Scenario-3:- 

We can use Partial Function where we don't have full definition for it's inputs.

Partial Function Interview Questions

That’s In this section, we will discuss some useful Scala Partial Functions related Interview Questions and Answers:

  • What is Partial Function?
  • What is Total Function?
  • What is the type of a Scala Partial Function?
         In Scala, the type of a  Partial Function is scala.PartialFunction[A,B]
  • When do we get a MatchError in a Partial Function?

That’s it all about “Scala Partial Functions”. We will discuss some more important Scala Concepts in my coming posts.

Please drop me a comment if you like my post or have any issues/suggestions. I love your valuable comments so much.