val even: PartialFunction[Int, String] = PartialFunction[Int, String] {
case i if i % 2 == 0 => i + " is even"
}
val isEven: PartialFunction[Int, String] = {
case i if i % 2 == 0 => i + " is even"
}
val odd: PartialFunction[Int, String] = PartialFunction[Int, String] {
case x if x % 2 == 1 => x + " is odd"
}
val isOdd: PartialFunction[Int, String] = {
case x if x % 2 == 1 => x + " is odd"
}
val tot = even orElse odd
val tot2 = isEven orElse isOdd
println(tot(3))
println(tot2(3))
In this code tot
function throws match error while tot2
function works as expected. Only difference between them is the way they're defined. Can anyone explain why such difference in result?
Thanks in advance!!!
// Creating Partial function1. val M : PartialFunction[Int, Int] = { // using case statement. case x if (x % 5 ) == 0 => x * 5.
Another example of a partial function is given by y = x + 1 x2 − 3x + 2 , assuming that both the input and output domains are R. This partial function “blows up” for x = 1 and x = 2, its value is “infinity” (= ∞), which is not an element of R. So, the domain of f is R − {1,2}.
Many properties of functions can be extended in an appropriate sense of partial functions. A partial function is said to be injective, surjective, or bijective when the function given by the restriction of the partial function to its domain of definition is injective, surjective, bijective respectively.
In Scala, a higher-order function is a function which takes another function as an argument. A higher-order function describes "how" the work is to be done in a collection. Let's learn the higher order function map. The map applies the function to each value in the collection and returns a new collection.
At the core the difference is that isDefinedAt on the partial function is not being defined as you would expect on the version using the PartialFunction.apply method. That is actually why this method is now deprecated, PartialFunction.apply is meant to convert a total function into a partial function with isDefinedAt always returning true, which means it will think it is defined for 3 in your example, and try to apply the function instead of falling back to the even function you have supplied as an alternative.
This brings up a common sore point in the community regarding total functions vs partial functions. PartialFunction is a subtype of Function, I guess in the OO design sense that it is a function with an additional method (isDefinedAt) which tells you whether the function is defined for a particular value. Many feel this is a mistake, as in the Liskov sense, Function should be a subtype of PartialFunction because you can use a Function anywhere a PartialFunction is expected, but if you use a PartialFunction where a Function is expected it will compile, then may fail at runtime. My feeling is that it is because Function can be considered to have an implicit isDefinedAt that always returns true, which would allow you to correct the relationship and make Function a subtype of PartialFunction. This comes to a head in PartialFunction.apply which expects a total function and due to this expectation defines isDefinedAt to always return true, but it can’t enforce that expectation, so if you call PartialFunction.apply(somePartialFunction) bad things happen that most programmers won’t expect.
PartialFunction.apply Scaladoc
PartialFunction[Int, String]{...} is syntactic sugar for
PartialFunction[Int, String].apply({...})
To minimize:
val even: PartialFunction[Int, String] = PartialFunction[Int, String]{
case i if i % 2 == 0 => i + " is even"
}
val isEven: PartialFunction[Int, String] = {
case i if i % 2 == 0 => i + " is even"
}
println(even.isDefinedAt(3)) //true
println(isEven.isDefinedAt(3)) //false
In the first two cases you are calling the apply
function in the companion object of PartialFunction
. I know, that sounds as if it should
work. But it doesn't because PartialFunction.apply
should read PartialFunction.fromTotalFunction
.
This is a scala language issue and, if I remember correctly (can't find the ticket at the moment, will look later), this apply
function will be gone and replaced by fromTotalFunction
in Scala 2.13.
UPDATE
The ticket I meant was #6005
It seems that PartialFunction.apply
is already deprecated since Scala 2.12.5.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With