Как я могу легко определить более сложные PartialFunctions в Scala?

PartialFunctions

В 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]

14
задан Andrzej Doyle 7 July 2011 в 14:47
поделиться