There are several things in your attempt, but first, consider a working implementation:
scala> val a: PartialFunction[String, Unit] = { case "hello" => println("bye") } a: PartialFunction[String,Unit] = <function1> scala> val b: PartialFunction[Any, Unit] = { case _ => println("fallback") } b: PartialFunction[Any,Unit] = <function1> scala> val c = a.orElse(b) c: PartialFunction[String,Unit] = <function1> scala> c("hello") bye scala> c("foo") fallback
There are two main errors in your code:
- method for determining PF
- (incorrect) assumption that
empty is a catch-all function that returns Nothing
1. How to determine PartialFunction
val right: PartialFunction[String, Unit] = { case "hello" => println("bye") }
How not to define it:
val wrong = PartialFunction[String, Unit] { case "hello" => println("bye") }
If you look at the definition of PartialFunction.apply
def apply[A, B](f: A => B): PartialFunction[A, B] = { case x => f(x) }
you will see that it defines a partial function for any x and applies the given function f to it. Now your { case "hello" => println("bye") } is an argument of f , so you will end up with the following (obviously unexpected) PartialFunction :
val wrong: PartialFunction[String, Unit] = { case x => x match { case "hello" => println("bye") }
So, when you ask if it will be defined, it will always return true, since it is defined for the any string:
wrong.isDefinedAt("hello") // true (ok) wrong.isDefinedAt("whatever") // true (sure?)
but when you try to apply it
wrong("hello") // bye (ok) wrong("whatever") // MatchError (BOOM!)
You do not agree with the coincidence inside .
Since orElse decides whether to call an "else" depending on the result of isDefined , then it is obvious why it fails.
2. Empty does not catch anything!
Straight from docs :
def empty[A, B]: PartialFunction[A, B]
Partial function with empty area. Any attempt to call an empty partial function scala.MatchError exception.
PartialFunction (well, this is not completely partial) that you are looking for:
val fallback: PartialFunction[Any, Unit] = { case _ => println("fallback") }
or - just to show that we learn from our mistakes -
val fallback = PartialFunction[Any, Unit] { _ => println("fallback") }