Каковы варианты использования Scala 2.9 в попытке... поймать обобщение?
Я читал о Scala 2.9 try...catch и экспериментировал с ним, и он заставил меня задуматься о возможностях. Что бы я на самом деле использовал для чего-то другого, кроме сохранения нескольких строк кода?
2 ответа
Вариант использования - возможность иметь общую обработку ошибок во всем приложении. Допустим, вы хотите справиться со всеми FileNotFoundException
s в вашем приложении, отправив электронное письмо администратору. Раньше вам приходилось делать это так:
// 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
,
Хороший ответ от axel22, но я думаю, что реальная причина его введения - это нечто другое. try
/catch
/finally
обработка ввела особый случай. Вы использовали литерал частичной функции, но на самом деле вы не могли заменить его частичной функцией. Сейчас, catch
просто получить частичную функцию, и еще один особый случай в языке исчез.