Search code examples
scalapartialfunction

Scala PartialFunction construction with different results


I was trying to debug why some partial function composition were not working when I noticed that depending on how you instantiate the partial function you get different results.

When you're using the syntactic sugar method it all works as expected:

scala> val pf1:PartialFunction[Any,Unit] = {case "a" => println("AAA")}
pf1: PartialFunction[Any,Unit] = <function1>

scala> val pf2:PartialFunction[Any,Unit] = {case "b" => println("BBB")}
pf2: PartialFunction[Any,Unit] = <function1>

scala> val pf = pf1 orElse pf2
pf: PartialFunction[Any,Unit] = <function1>

scala> pf("a")
AAA

scala> pf("b")
BBB

However, if you use the PartialFunction object it doesn't work anymore.

scala> val pf1 = PartialFunction[Any,Unit]{case "a" => println("AAA")}
pf1: PartialFunction[Any,Unit] = <function1>

scala> val pf2 = PartialFunction[Any,Unit]{case "b" => println("BBB")}
pf2: PartialFunction[Any,Unit] = <function1>

scala> val pf = pf1 orElse pf2
pf: PartialFunction[Any,Unit] = <function1>

scala> pf("a")
AAA

scala> pf("b")
scala.MatchError: b (of class java.lang.String)
at $anonfun$1.apply(<console>:7)

Why is that? You usually grow to expect that the apply method of an Object behaves like the constructor of the Class.


Solution

  • As others noted, PartialFunction.apply converts an ordinary function into a partial function.

    The only reasonable way to do this, since the domain of the ordinary function is unknown (as far as PartialFunction.apply is concerned), is to create a partial function defined everywhere.

    So when you write PartialFunction[Any,Unit] { case "a" => println("AAA") }, you're actually creating two partial functions: the one passed into the apply method and the one returned by the apply method. They're almost the same, except that the returned function is defined everywhere and not just at "a".