是否可以使用部分函数分解 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)
我有这样的匹配语句:
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)