Home > Software engineering >  Factoring out common cases in pattern matching with partial function
Factoring out common cases in pattern matching with partial function

Time:12-06

I routinely use partial functions to factor out common clauses in exception handling. For example:

val commonHandler: PartialFunction[Throwable, String] = {
  case ex: InvalidClassException => "ice"
}

val tried = try {
  throw new Exception("boo")
}
catch commonHandler orElse {
  case _:Throwable => "water"
}

println(tried) // water

Naturally, I expected that the match keyword also expects a partial function and that I should be able to do something like this:

  val commonMatcher: PartialFunction[Option[_], Boolean] = {
    case Some(_) => true
    case None => false
  }

  Some(8) match commonMatcher // Compilation error

What am I doing wrong?

CodePudding user response:

The match is a keyword, not a method, and its syntax does not accept a partial function on its right side (see below). There however exists a pipe method (since 2.13), which, same as map or foreach, accepts a partial function. You can therefore write:

import scala.util.chaining._

Some(8).pipe(commonMatcher)

There was some discussion regarding this (see Pre SIP: Demote match keyword to a method) and there was a PR which made possible to use the match a bit more like a method (Change match syntax #7610), with a dot, but still the syntax is the match keyword needs to be followed by case clauses, see https://docs.scala-lang.org/scala3/reference/syntax.html:

InfixExpr         ::=  ... other variants ommitted here ...
                    |  InfixExpr MatchClause

SimpleExpr        ::=  ... other variants ommitted here ...
                    |  SimpleExpr ‘.’ MatchClause

MatchClause       ::=  ‘match’ <<< CaseClauses >>>

CaseClauses       ::=  CaseClause { CaseClause }
CaseClause        ::=  ‘case’ Pattern [Guard] ‘=>’ Block

Compare this with catch syntax:

Expr1             ::=  ... other variants ommitted here ...
                    |  ‘try’ Expr Catches [‘finally’ Expr]

Catches           ::=  ‘catch’ (Expr | ExprCaseClause)
  • Related