为什么`scala.util.Try`在章节“没有例外处理错误”中没有提及的书“Scala中的功能编程”? [英] Why `scala.util.Try` is not mentioned in chapter "Handling errors without exceptions" of book "functional programming in Scala"?

查看:124
本文介绍了为什么`scala.util.Try`在章节“没有例外处理错误”中没有提及的书“Scala中的功能编程”?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Scala中的功能编程一书的处理错误无异常一章中,作者给出了:

In the chapter "Handling errors without exceptions" of book "functional programming in Scala", the author gives:


  1. 从函数体中抛出异常

  2. 如果不关心实际异常,请使用 Option

  3. 如果我们关心实际异常,请使用

但是没有提到 scala.util.Try 从我的角度来看,我认为尝试非常适合当我们关心实际异常,为什么没有提及?有没有任何错误的原因?

But scala.util.Try is not mentioned. From my point of view, I think Try is very suitable when we care about the actual exception, why it's not mentioned? Is there any reason I have missed?

推荐答案

我不是Scala中功能编程的作者,但我可以有几个猜测为什么他们不提到尝试

I'm neither of the authors of Functional Programming in Scala, but I can make a few guesses about why they don't mention Try.

有些人不喜欢标准库的尝试因为他们声称它违反了functor组成法 。我个人认为这个立场是愚蠢的,因为Josh Suereth在SI-6284的评论中提及的原因,但辩论确实突出了的一个重要方面。尝试设计。

Some people don't like the standard library's Try because they claim it violates the functor composition law. I personally think that this position is kind of silly, for the reasons Josh Suereth mentions in the comments of SI-6284, but the debate does highlight an important aspect of Try's design.

尝试地图 flatMap 被明确设计用于处理可能引发异常的函数。 FPiS思想学派(包括我)的人们倾向于建议在程序中的低级别安全版本中包含这些功能(如果你绝对必须处理它们),然后暴露一个永远不会抛出的API (非致命的)例外。

Try's map and flatMap are explicitly designed to work with functions that may throw exceptions. People from the FPiS school of thought (including me) would tend to suggest wrapping such functions (if you absolutely have to deal with them at all) in safe versions at a low level in your program, and then exposing an API that will never throw (non-fatal) exceptions.

包含尝试在您的API中混乱了这个模型中的图层 - 重新保证您的API方法不会抛出异常,但是您正在将人们设计为与抛出异常的函数一起使用的类型。

Including Try in your API muddles up the layers in this model—you're guaranteeing that your API methods won't throw exceptions, but then you're handing people a type that's designed to be used with functions that throw exceptions.

这只是一个抱怨标准图书馆的设计和执行尝试。很容易想象出一个版本的尝试具有不同的语义,其中映射 flatMap 方法没有捕获异常,并且尽可能避免这种改进版本的尝试仍然有很好的理由。

That's only a complaint about the standard library's design and implementation of Try, though. It's easy enough to imagine a version of Try with different semantics, where the map and flatMap methods didn't catch exceptions, and there would still be good reasons to avoid this "improved" version of Try whenever possible.

其中一个原因是使用 [MyExceptionType,A] 而不是尝试[A] 使得可以从编译器的详尽性检查中获得更多的里程。假设我在应用程序中使用以下简单的ADT错误:

One of these reasons is that using Either[MyExceptionType, A] instead of Try[A] makes it possible to get more mileage out of the compiler's exhaustivity checking. Suppose I'm using the following simple ADT for errors in my application:

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"
)

现在我试图决定是否只能 / em>以这两种方式之一失败应该返回 [FooAppError,A] 尝试[A] 。选择尝试[A] 意味着我们将丢弃对人类用户和编译器有用的信息。假设我写了一个这样的方法:

Now I'm trying to decide whether a method that can only fail in one of these two ways should return Either[FooAppError, A] or Try[A]. Choosing Try[A] means we're throwing away information that's potentially useful both to human users and to the compiler. Suppose I write a method like this:

def doSomething(result: Either[FooAppError, String]) = result match {
  case Right(x) => x
  case Left(MissingField(_)) => "bad"
}

我会得到一个很好的编译时间警告告诉我比赛并不详尽。如果我为错误的错误添加了一个案例,则警告消失。

I'll get a nice compile-time warning telling me that the match is not exhaustive. If I add a case for the missing error, the warning goes away.

如果我使用了 Try [String] 而是,我也会进行详尽的检查,但是摆脱警告的唯一办法就是要抓住所有情况 - 只是不可能枚举所有的 Throwable s在模式匹配。

If I had used Try[String] instead, I'd also get exhaustivity checking, but the only way to get rid of the warning would be to have a catch-all case—it's just not possible to enumerate all Throwables in the pattern match.

有时我们实际上无法方便地限制操作可能失败的方式,我们自己的失败类型(如 FooAppError 以上),在这些情况下,我们总是可以使用 [Throwable,A] 。例如,Scalaz的任务本质上是 Future [Throwable \ / A] 的包装器。不同之处在于(或 \ / 支持这种签名,而尝试 需要。并不总是你想要的,因为有用的详尽性检查的原因。

Sometimes we actually can't conveniently limit the kinds of ways an operation can fail to our own failure type (like FooAppError above), and in these cases we can always use Either[Throwable, A]. Scalaz's Task, for example, is essentially a wrapper for Future[Throwable \/ A]. The difference is that Either (or \/) supports this kind of signature, while Try requires it. And it's not always what you want, for reasons like useful exhaustivity checking.

这篇关于为什么`scala.util.Try`在章节“没有例外处理错误”中没有提及的书“Scala中的功能编程”?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆