是否可以使用部分函数分解 Scala 匹配语句?

Is it possible to decompose Scala match statements using partial functions?

我有这样的匹配语句:

    i match {
      case x if x == 0 ⇒
        romanNumeral

      case x if x >= 1000 ⇒
        this.roman(i - 1000, s"${romanNumeral}M")

      case x if x >= 900 ⇒
        this.roman(i - 900, s"${romanNumeral}CM")

      // etc.

根据格式的不同,可能会有大约 30 行冗余代码。 所以我想知道是否可以让这段代码更干

所以我创建了一个偏函数:

  private def toRoman(upperGuard: Int, token: String, romanNumeral: String): String = {
    case value: Int if value >= upperGuard ⇒
      this.roman(upperGuard - 1, s"$romanNumeral$token")
  }

然后我尝试将其包含到上面的匹配器中,例如:

    i match {
      case x if x == 0 ⇒
        romanNumeral

        toRoman(1000, "M", romanNumeral)
        toRoman(900, "CM", romanNumeral)
        // etc.

...但这行不通,因为 Scala 的编译器无法识别这些函数是它正在寻找的 case 语句。

有什么方法可以实现吗?

所以你基本上是想减少代码的重复性,首先要做的是:

  • Scala 的编译器不会将这些函数识别为 case 语句,因为它们是函数;
  • 第二,那个函数实际上不是偏函数;
  • 最后,如果你找到一种通过分组某种函数来减少代码行的方法,就像你做得很好但我不觉得它们是多余的,除非你可以重做它具有我所说的功能。

Ps: 这个函数不做某些事

您没有模式匹配表达式,您只是在编写 if else 语句。如果你想return一个函数,你会写:x => this.something(x,"foo-bar")你不需要case x。如果 LHS case x 上只有一个表达式,则不需要模式匹配,只需使用 if else。没有 class 层次结构的模式匹配没有意义。

您可以将案例创建为部分函数:

private def toRoman(upperGuard: Int, token: String, romanNumeral: String): PartialFunction[Int, String] = {
    case value if value >= upperGuard =>
      this.roman(upperGuard - 1, s"$romanNumeral$token")
}

val firstCase: PartialFunction[Int, String] = {
    case x if x == 0 => romanNumeral
}

然后这样写:

val toRomanPartialFunction = firstCase
  .orElse(toRoman(1000, "M", romanNumeral))
  .orElse(toRoman(900, "CM", romanNumeral))

之后你就可以像普通函数一样使用它了:

toRomanPartialFunction.apply(443) 
toRomanPartialFunction(443)