В Scala, PartialFunction
, вкратце, является функцией, которая дополнительно определяет метод isDefinedAt
.
Это легко определить частичные функции с серией операторов case
. Тривиальным примером может быть, например:
scala> val pf: PartialFunction[Int, Unit] = {
| case 42 => ()
| }
pf: PartialFunction[Int,Unit] =
scala> pf.isDefinedAt(42)
res0: Boolean = true
scala> pf.isDefinedAt(0)
res1: Boolean = false
isDefinedAt
автоматически генерируется из списка case
s, определяющих частичную функцию.
Платформа Lift использует частичные функции во многих местах, например чтобы определить, должен ли запрос обрабатываться движком Lift или обслуживаться непосредственно из файла на диске, как есть. а иногда мне хочется написать оператор case
, который соответствует всем входным параметрам и только позже решает, хочу я вернуть значение или нет. Это означает, что исходной серии case
s больше недостаточно, чтобы определить, определена ли моя функция с заданным значением или нет
. Например, в Lift я хочу добавить правило, что все Файлы html и htm обслуживаются напрямую, и файлы с расширением «lift» должны обрабатываться.Было бы легко сделать что-то вроде этого:
LiftRules.liftRequest.prepend {
case Req(path, extension, tpe) => extension match {
case "html" | "htm" => false
case "lift" => true
}
}
К сожалению, в этом случае компилятор думает, что моя частичная функция определена везде, поскольку первый case
всегда совпадает. Это вложенное совпадение
, которое может не соответствовать всем входящим запросам. И если запрос не соответствует, выдается MatchError
.
Есть ли простой способ заставить компилятор учитывать вложенные операторы match
при определении частичного
LiftRules.liftRequest.prepend {
case Req(path, extension, tpe) if extension == "html" || extension == "htm" => false
case Req(path, extension, tpe) if extension == "lift" => true
}
В этом примере это в значительной степени выполнимо, но читабельность снижена, и я сталкивался со случаями, когда встраивание всех проверок выглядит очень некрасиво.
LiftRules.liftRequest.prepend {
case Req(path, extension, tpe) if extension == "html" || extension == "htm" => false
case Req(path, extension, tpe) if extension == "lift" => true
}
11143788]