Fre*_*ind 21 scala exception either
在"Scala中的函数式编程"一书的"无异常处理错误"一章中,作者给出了:
Option,如果我们不关心实际的异常Either如果我们关心实际的异常但scala.util.Try没有提到.从我的角度来看,我认为Try当我们关心实际的异常时,它是非常合适的,为什么没有提到呢?我错过了什么理由?
Tra*_*own 49
我既不是Scala中的函数编程的作者,但我可以猜测为什么他们不提Try.
有些人不喜欢标准库,Try因为他们声称它违反了仿函数组成法.我个人认为这个位置有点愚蠢,因为Josh Suereth在SI-6284的评论中提到的原因,但辩论确实强调了Try设计的一个重要方面.
Try的map和flatMap明确设计与可能抛出异常职能工作.来自FPiS思想学派(包括我)的人倾向于建议在程序中的低级安全版本中包装这些函数(如果你绝对必须处理它们),然后公开一个永不抛出的API (非致命)例外.
包含Try在你的API中会混淆这个模型中的图层 - 你保证你的API方法不会抛出异常,但是你会给人们一个设计用于抛出异常的函数的类型.
不过,这只是对标准库的设计和实现的抱怨Try.很容易想象一个Try具有不同语义的版本,其中map和flatMap方法没有捕获异常,并且仍然有充分的理由尽可能避免这种"改进"版本Try.
其中一个原因是使用Either[MyExceptionType, A]而不是Try[A]使得可以从编译器的穷举检查中获得更多的里程数.假设我在我的应用程序中使用以下简单的ADT来解决错误:
sealed class FooAppError(message: String) extends Exception(message)
case class InvalidInput(message: String) extends FooAppError(message)
case class MissingField(fieldName: String) extends FooAppError(
s"$fieldName field is missing"
)
Run Code Online (Sandbox Code Playgroud)
现在,我正在尝试确定一种只能以这两种方式之一失败的方法应该返回Either[FooAppError, A]还是Try[A].选择Try[A]意味着我们丢弃了对人类用户和编译器都有用的信息.假设我写了一个这样的方法:
def doSomething(result: Either[FooAppError, String]) = result match {
case Right(x) => x
case Left(MissingField(_)) => "bad"
}
Run Code Online (Sandbox Code Playgroud)
我会得到一个很好的编译时警告,告诉我这场比赛并非详尽无遗.如果我为丢失的错误添加一个案例,警告就会消失.
如果我曾经使用过Try[String],我也会进行穷举检查,但摆脱警告的唯一方法就是拥有一个包罗万象的案例 - 它不可能枚举Throwable模式匹配中的所有s.
有时我们实际上不能方便地限制操作失败到我们自己的失败类型的方式(FooAppError如上所述),在这些情况下我们总是可以使用Either[Throwable, A].Task例如,Scalaz 本质上是一个包装器Future[Throwable \/ A].不同之处在于Either(或\/)支持这种签名,同时Try 需要它.由于有用的穷举检查等原因,并不总是你想要的.
| 归档时间: |
|
| 查看次数: |
1752 次 |
| 最近记录: |