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?
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)