Каковы варианты использования для Scala 2.9 try... catch generalization?

Я читал и экспериментировал с функцией Scala 2.9 try... catch, и он задумывался о возможностях. Что бы я на самом деле использовал для других, кроме сохранения нескольких строк кода?

Scala 2.9 Примечания к окончательной версии

Ответы

Ответ 1

Вариант использования должен иметь общую обработку ошибок во всем приложении. Скажем, вы хотите обрабатывать все FileNotFoundException в своем приложении, отправив электронное письмо администратору. Раньше вам приходилось делать это следующим образом:

// Globally
val fileNotFound: PartialFunction[Throwable, Unit] = {
  case e: FileNotFoundException =>
    // Create report and send the e-mail
}

// On each try-catch-block
try {
  // Open file
} 
catch {
  case fnf: FileNotFoundException => fileNotFound(fnf)
}

Теперь вы просто выполните:

try {
  // Open file
} catch fileNotFound

Это также имеет хорошее преимущество, что вы можете связать несколько таких обработчиков исключений, используя метод orElse для частичных функций:

val fileErrors = fileNotFound orElse endOfFile orElse invalidFormat

И тогда просто используйте это везде, где вам нужна обработка исключений файлов. Например, такой обработчик ошибок можно динамически комбинировать на основе файла конфигурации для приложения. Это гораздо менее громоздко, чем сопоставление шаблонов во всем мире и вызов правильного обработчика.

Одна полезная вещь, которая может быть ограничена сверху частичных функций, - это оператор andAlso, который действует как оператор секвенции на двух частичных функциях. Это было бы полезно, если вы захотите выполнить некоторую обработку ошибок, относящуюся к определенному блоку try-catch, после выполнения общей обработки ошибок.

implicit def pf2ops(pf: PartialFunction[Throwable, Unit]) = new {
  def andAlso(localpf: PartialFunction[Throwable, Unit]) = new PartialFunction[Throwable, Unit] {
    def apply(t: Throwable) = {
      if (pf.isDefinedAt(t)) pf(t)
      localpf(t)
    }
    def isDefinedAt(t: Throwable) = pf.isDefinedAt(t) || localpf.isDefinedAt(t)
  }
}

И тогда вы можете это сделать:

scala> try {
     |   throw new java.io.FileNotFoundException
     | } catch fnf andAlso {
     |   case e: Exception => println("I don't know, but something is specific to this particular block.")
     | }
I don't know, but something is specific to this particular block.

Я думаю, вы могли бы играть дальше с точной семантикой и значением (и именем) andAlso.

Ответ 2

Хороший ответ axel22, но я думаю, что настоящая причина его введения - это что-то еще. Обработка try/catch/finally ввела специальный случай. Вы использовали литерал частичной функции, но вы не могли заменить его частичной функцией. Теперь catch просто получает частичную функцию, а еще один специальный случай на этом языке отсутствует.