是否等同于已检查的异常?

时间:2012-05-30 14:33:11

标签: scala functional-programming

从Scala开始并阅读Either我自然地将新概念与我所知道的事物进行比较(在本例中来自Java)。与已检查的例外和Either概念有什么不同吗?

在这两种情况下

  • 在方法中明确注释失败的可能性(throws或返回Either
  • 程序员可以直接处理错误案例或将其移动(再次返回Either
  • 有一种方法可以通知来电者错误原因

我想在Either上使用for-comprehensions来编写代码,因为不存在类似于checked异常的错误。

我想知道我是否是唯一一个遇到问题的初学者。

由于

3 个答案:

答案 0 :(得分:12)

Either不仅可用于例外。例如,如果您要让用户为您输入输入或指定包含该输入的文件,则可以将其表示为Either[String, File]

Either经常用于异常处理。 Either和已检查异常之间的主要区别在于Either的控制流始终是显式的。编译器真的不会让你忘记你正在处理Either;如果没有您的意识,它将不会从多个地方收集Either,返回的所有内容都必须是Either等。因此,您不能使用Either也许某些特殊的东西会出错,但作为控制程序执行的正常部分。此外,Either不捕获堆栈跟踪,使其比典型异常更有效。

另一个区别是异常可用于控制流程。需要跳出三个嵌套循环?没问题 - 抛出一个异常(没有堆栈跟踪)并在外面捕获它。需要跳出五个嵌套方法调用吗?没问题!要么不提供这样的东西。

那就是说,正如你所指出的,有许多相似之处。您可以传回信息(虽然Either使得这些变得微不足道,而经过检查的异常会让您编写自己的类来存储您想要的任何额外信息);你可以通过Either或者你可以把它折叠成别的东西等等。

因此,总结一下:虽然您可以使用Either完成相同的事情并检查有关显式错误处理的异常,但它们在实践中相对不同。特别是,Either使得创建和传回不同的状态变得非常容易,而经过检查的异常很好地绕过了所有正常的控制流程,希望能够回到可以合理处理特殊情况的某个地方。 p>

答案 1 :(得分:2)

是的,Either是一种在一种语言中嵌入异常的方法;其中一组可能失败的操作可能会将错误值抛出到某个非本地站点。

除了Rex提到的实际问题之外,你还可以从Either的简单语义中得到一些额外的东西:

  • Either形成一个monad;因此,您可以对评估为Either的表达式集合使用monadic操作。例如。用于短路评估而无需测试结果
  • Either属于类型 - 因此单独的类型检查器就足以跟踪错误的值处理

一旦您能够返回错误消息(Left s)或成功值Right v,您就可以将异常排在最前面,只需Either加上错误处理程序,就像完成for MonadError in Haskell

答案 2 :(得分:2)

在形成exclusive disjunction的返回签名方面,两者都等同于已检查的异常。结果可以是抛出的异常X或A.但是,抛出异常并不等同于返回异常 - 第一个不是引用透明的。

当Scala的Either不是(截至2.9)等价的是返回类型是正偏置的,并且需要努力提取/解构异常,要么是无偏的;你需要明确要求左或右值。这是一个topic of some discussion,实际上有点痛苦 - 考虑以下三个调用生成方法

for {
  a <- eitherA("input").right
  b <- eitherB(a).right
  c <- eitherC(b).right
} yield c // Either[Exception, C]

您需要手动穿过RHS。这看起来似乎并不繁琐,但实际上对于新来者来说是一种痛苦而且有点令人惊讶。