Search code examples
scalafunctionpartialfunction

Composing partial functions in Scala


I have two partial functions f1 and f2 which I want to compose into a new partial function f so that f.isDefinedAt(x) iff f1.isDefinedAt(x) || f2.isDefinedAt(x). I mean

        --
       | f1(x) iff f1.isDefinedAt(x)  
       |
f(x) = |
       |
       | f2(x) iff  !f1.isDefinedAt(x) && f2.isDefinedAt(x)  
        --

Is there a way to compose f1 and f2 that way?


Solution

  • Use method .orElse on PartialFunction:

    scala> val f1: PartialFunction[Int, Unit] = { case x if x > 0 => println(s"called f1 with $x") }
    f1: PartialFunction[Int,Unit] = <function1>
    
    scala> val f2: PartialFunction[Int, Unit] = { case x if x < 0 => println(s"called f2 with $x") }
    f2: PartialFunction[Int,Unit] = <function1>
    
    scala> (f1 orElse f2)(1)
    called f1 with 1
    
    scala> (f1 orElse f2)(-1)
    called f2 with -1
    
    scala> (f1 orElse f2)(0)
    scala.MatchError: 0 (of class java.lang.Integer)
      at scala.PartialFunction$$anon$1.apply(PartialFunction.scala:253)
      at scala.PartialFunction$$anon$1.apply(PartialFunction.scala:251)
      at $anonfun$1.applyOrElse(<console>:11)
      at $anonfun$1.applyOrElse(<console>:11)
      at scala.runtime.AbstractPartialFunction$mcVI$sp.apply$mcVI$sp(AbstractPartialFunction.scala:36)
      at scala.runtime.AbstractPartialFunction$mcVI$sp.apply(AbstractPartialFunction.scala:36)
      at scala.runtime.AbstractPartialFunction$mcVI$sp.apply(AbstractPartialFunction.scala:28)
      at $anonfun$1.applyOrElse(<console>:11)
      at $anonfun$1.applyOrElse(<console>:11)
      at scala.PartialFunction$OrElse.apply(PartialFunction.scala:167)
      at scala.Function1$class.apply$mcVI$sp(Function1.scala:36)
      at scala.PartialFunction$OrElse.apply$mcVI$sp(PartialFunction.scala:164)
      ... 32 elided