Каковы варианты использования Scala 2.9 в попытке ... поймать обобщение? - PullRequest
20 голосов
/ 17 октября 2011

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

Замечания к финальному выпуску Scala 2.9

Ответы [ 2 ]

25 голосов
/ 17 октября 2011

Вариант использования - возможность иметь общую обработку ошибок во всем приложении. Допустим, вы хотите обработать все 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.

7 голосов
/ 06 ноября 2011

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...