Частичные функции
В Scala PartialFunction
, короче говоря, функция, которая дополнительно определяет метод isDefinedAt
.
Частичные функции легко определить с помощью серии операторов case
. Тривиальным примером может быть, например:
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
автоматически генерируется из списка 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
всегда совпадает. Это вложенный match
, который может не соответствовать всем входящим запросам. И если запрос не соответствует, выдается 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
}
В этом примере это в основном выполнимо, но удобочитаемость снижается, и я сталкивался со случаями, когда встраивание всех проверок выглядит очень некрасиво.