我已经阅读并尝试了Scala 2.9 try ... catch功能,它让我思考可能性。除了保存几行代码之外,我实际上会将它用于什么?
答案 0 :(得分:25)
用例是能够在整个应用程序中进行一般错误处理。假设您希望通过向管理员发送电子邮件来处理应用程序中的所有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
的确切语义和含义(以及名称)。
答案 1 :(得分:7)
axel22的答案很好,但我认为引入它的真正原因是别的。 try
/ catch
/ finally
处理引入了特殊情况。您使用了部分函数文字,但实际上您无法用部分函数替换它。现在,catch
只接收部分功能,语言中的另一个特殊情况就消失了。