Partial Function In Scala
val aFunction = (x: Int) => x + 1
Here aFunction is an instance of Function1[Int, Int] ===== (Int) => (Int) which will accept "any int value" and return with plus 1.
But what if we need aFunction that accepts "a certain part of int" like {1, 2, 3, 4, 5} only, And for the rest of the int value should not be applicable.
Let's create another function aFussyFunction that will throw an exception if the value goes out of {1, 2, 3, 4, 5}.
val aFussyFunction = (x: Int) => {
if(x >= 1 && x<=5) x + 1
else throw new FunctionNotApplicableException
}
class FunctionNotApplicableException extends RuntimeException
val aNicerFussyFunction = (x: Int) => x match
case x if x >= 1 && x <= 5 => x + 1
because {1, 2, 3, 4, 5} is a subset of int so this is called a partial function form "Int => Int". why partial? because it accepts only a part of the int domain as an argument.
Scala supports the partial implementation using PartialFunction, and shorthand notation for writing it is following:
val aPartialFunction: PartialFunction[Int, Int] = {
case x if x >= 1 && x <= 5 => x + 1
}
{ .... } is a partial function value and equivalent to "aNicerFussyFunction"
领英推荐
Partial functions as we see here will act like proper functions, in the sense that they can be called and used like any other functions.
// here we are calling a apply method of PartialFunction[Int, Int]
val aPartialFunctionResult = aPartialFunction(2)
At this point, we understand partial functions and their applications. Below are some partial function utilities.
aPartialFunction.isDefinedAt(10)
val lifted: Int => Option[Int] = aPartialFunction.lift
val pfChain: PartialFunction[Int, Int] = aPartialFunction.orElse{ case 10 => 10 + 1 }
PF can be used to provide an implementation of total function because PF is a subtype of total function.
val aTotalFunction: Int => Int = { case 1 => 99 }
Because of the above, our favorite HOF like map, flatMap, filter accepts PF as well.
val aMappedList = List(1, 2, 3).map{ case 1 => 42 case 2 => 76 case 3 => 1000 } println(aMappedList) // List(42, 76, 1000) val aErrorMappedList = List(1, 2, 3).map{ case 1 => 42 case 2 => 76 case 5 => 1000 } println(aErrorMappedList) // Caused by: scala.MatchError: 3