存在通配符时使用 orElse 组合 PartialFunctions

Composing PartialFunctions with orElse when there is a wildcard case

当第一个函数具有 case _ => 匹配任何东西的通配符模式时,是否可以 orElse 组合两个 PartialFunction,因此实际上是一个总函数。

例如给定

val pf1: PartialFunction[Int, String] = {
  case 1 => "foo"
  case 2 => "bar"
  case _ => "wildcard"
}

val pf2: PartialFunction[Int, String] = {
  case 3 => "baz"
  case _ => "wildcard"
}

然后,开箱即用

(pf1 orElse pf2)(3)

输出wildcard。但是,假设我们不能修改 pf1,我们可以使用一些 compfnpf2 组合,这样我们就可以生效

{
  case 1 => "foo"
  case 2 => "bar"
  case 3 => "baz"
  case _ => "wildcard"
}

其中 (pf1 compfn pf2)(3) 会输出 baz?

为什么不选择这样的东西:

val pf1: PartialFunction[Int, String] = {
  case 1 => "foo"
  case 2 => "bar"
}

val pf2: PartialFunction[Int, String] = {
  case 3 => "baz"
}

def composeOrElseWildcard(input: Int) = (pf1 orElse pf2).applyOrElse(input,(_: Int) => "wildcard")

否则,对我来说,pf1.

中没有消除通配符模式效果的解决方案

( composeOrElseWildcard(3) 给出 "baz" 而 composeOrElseWildcard(4) 给出 "wildcard" )

您可以通过执行第二个 match 将 "wildcard" 结果转换为失败的匹配,从而将 pf1 变成真正的偏函数。

val pf3: PartialFunction[Int, String] = (i: Int) => pf1(i) match {
  case s if s != "wildcard" => s
}

然后

(pf3 orElse pf2)(3)

如果您想要显示的精确语法,则需要使用隐式 class:

implicit class addCompfn(f1: PartialFunction[Int, String]) {
  def compfn(f2: PartialFunction[Int, String]) = (i: Int) => f1(i) match {
    case s if s != "wildcard" => s
    case s => f2(i)
  }
}

然后

(pf1 compfn pf2)(3)