PartialFunctions
In Scala, a PartialFunction
is, in short, a function that additionally defines an isDefinedAt
method.
It is easy to define partial functions with a series of case
statement. A trivial example would be, e.g.:
scala> val pf: PartialFunction[Int, Unit] = {
| case 42 => ()
| }
pf: PartialFunction[Int,Unit] = <function1>
scala> pf.isDefinedAt(42)
res0: Boolean = true
scala> pf.isDefinedAt(0)
res1: Boolean = false
isDefinedAt
is automatically generated from the list of case
s defining the partial function.
Context
The Lift framework makes use of partial functions in many places, e.g. to define whether a request should be processed by Lift's engine or served directly from a file on disk, as is. and sometimes, I find myself wanting to write a case
statement that matches all input parameters and only later decide if I want to return a value or not. This means that the initial series of case
s is not enough any more to determine if my function is defined at a given value or not
For instance, in Lift, I want to add a rule that all html and htm files are served directly, and that files with the “lift” extension should be processed. It would look easy to do something like this:
LiftRules.liftRequest.prepend {
case Req(path, extension, tpe) => extension match {
case "html" | "htm" => false
case "lift" => true
}
}
Unfortunately, in this case, the compiler thinks that my partial function is defined everywhere, as the first case
always matches. It's the nested match
that may not match all incoming requests. And, is a request is not matched, a MatchError
is thrown.
Question
Is there a simple way to make the compiler consider nested match
statements when defining a partial function, or is the only way to do it to inline all nested conditionals like this?
LiftRules.liftRequest.prepend {
case Req(path, extension, tpe) if extension == "html" || extension == "htm" => false
case Req(path, extension, tpe) if extension == "lift" => true
}
In this example, it's largely doable, but the readability is decreased, and I've faced cases where inlining all checks looks very ugly.