PartialFunctions
В Scala a 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
, определяющего частичную функцию.
Контекст
Рамка Lift использует частичные функции во многих местах, например. определить, должен ли запрос обрабатываться движком Lift или подаваться непосредственно из файла на диске, как есть. и иногда я хочу написать инструкцию case
, которая соответствует всем входным параметрам, и только позже решить, хочу ли я вернуть значение или нет. Это означает, что исходной серии case
недостаточно, чтобы определить, определена ли моя функция по заданному значению или нет
Например, в приложении "Лифт" я хочу добавить правило, что все файлы 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
}
В этом примере это в значительной степени выполнимо, но читаемость уменьшена, и я столкнулся с ситуациями, когда инкрустация всех проверок выглядит очень уродливо.