Yog*_*til 5 scala exception-handling exception
我有以下两个问题:
Tia*_*gel 12
我不知道Scala选择不检查异常的确切原因,但可以说这是常见的方法,你知道除了java之外还有多少其他语言检查了异常?
我会指出我多年来在很多java程序中看到的东西,我敢肯定你是否认真对待java编程你也看过它.
try {
// do stuff
} catch (Exception e) {
throw new RuntimeException(e);
}
try {
// do stuff
} catch (Exception e) {
// do nothing
}
Run Code Online (Sandbox Code Playgroud)
当然你可以说这是懒惰的编程,而后者确实是.但它显示了一个问题,你有时不能也不想处理异常,你希望程序中断,或者异常冒泡到更高级别的组件来处理错误.
而你现在可能正在思考你只需要在方法签名中添加抛出,但更多时候你不能.我可以使用java 8 lambdas给你一个明确的例子.
list.stream().map(item -> {
// throws a checked exception. compilation error
return normalizeItem(item);
});
Run Code Online (Sandbox Code Playgroud)
在上面的代码中,您需要使用上面显示的两种技术之一来处理异常.你当然可以创建一个抛出异常的新功能界面,但是你需要重新创建所有标准的界面,只是为了用抛出来对它们进行旋转.如果你问我,这真是一团糟.
我认为这是其中一个原因,scala从一开始就具有功能,并且检查异常与此不相符,如您所见.
您可以在此处阅读更全面的讨论
小智 7
TL; DR跳到最后一段:)
虽然我完全赞同蒂亚戈的答案,但有一些事情可以补充.如您所知,Scala是一种功能性和面向对象的语言.它的功能方面规定应消除副作用,或至少尽可能减少副作用.
抛出异常的副作用,因为它是不引用透明(即,它取决于其中引发异常的情况下,例如,如果异常是从一个try块内抛出,它会被抓住而如果它是抛出那个try块之外,它会改变程序的流程).
以下是Scala中的函数式编程一书中的一个例子(P. Chiusano,R.Bjarnason)
def failingFn(i: Int): Int = {
val y: Int = throw new Exception("fail!")
try {
val x = 42 + 5
x + y
}
catch { case e: Exception => 43 }
}
Run Code Online (Sandbox Code Playgroud)
在上面的代码中,y不是引用透明的,因为如果用try块中的值替换它,函数的结果将是不同的.
好吧,对于所有的理论来说,从上面得到的关键是,抛出异常是一种副作用,这违反了函数式编程范式.
为了解决这个问题,Scala的设计者决定返回"值",表示发生了异常,而不是抛出异常.出于这个原因,引入了像Try(及其直接子类型Success and Failure)这样的类.您只需修改函数的返回类型,将其包装在Try中,而不是抛出异常.这会强制客户端检查成功或失败,而不会产生抛出异常带来的所有副作用.Try类型的引入基本上替换了已检查的异常,因为通过使用Try返回类型,客户端在编译时隐式地意识到异常的可能性.