Brian Kessler
Brian Kessler

Reputation: 2327

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

I have a match statement like this:

    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.

Depending on how this is formatted, it could be about 30 lines of redundant code. So I'm wondering whether it is possible to make this code more dry.

So I created a partial function:

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

which I then tried to include into the above matcher like:

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

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

... But this won't work because Scala's compiler doesn't recognize these functions are the case statements it is looking for.

Is there any way to make this work?

Upvotes: 0

Views: 224

Answers (3)

Krzysztof Atłasik
Krzysztof Atłasik

Reputation: 22595

You could create your cases as partial functions:

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
}

And then compose it like this:

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

After that you could use it like regular function:

toRomanPartialFunction.apply(443) 
toRomanPartialFunction(443) 

Upvotes: 2

Derrops
Derrops

Reputation: 8107

You don't have a pattern matching expression, you are just writing an if else statement. If you want to return a function, you would write: x => this.something(x,"foo-bar") You have no need for case x. If you are only having one expression on the LHS case x you have no need for pattern matching, and can just use if else. Pattern matching without a class hierarchy doesn't make sense.

Upvotes: -1

Pedro Correia Luís
Pedro Correia Luís

Reputation: 1095

So you basically want to make the code less repetitive, first things first:

  • Scala´s compiler doesn't recognise these functions as case statements because they are functions;
  • Second thing, that function is not actually a partial function;
  • Finally, those matches are ok to be like that, if you find a way of reducing lines of code by grouping in some kind of function like you did great but I don't find them redundant, unless you can redo it with a function like I said.

Ps: That function don't do the some thing as the case

Upvotes: 0

Related Questions