Scala 中抛出异常,什么是“官方规则”

2024-05-12

我正在 Coursera 上学习 Scala 课程。 我也开始阅读 Odersky 的 Scala 书。

我经常听到的是,在函数式语言中抛出异常不是一个好主意,因为它破坏了控制流,并且我们通常返回一个失败或成功的“Either”。 Scala 2.10 似乎也将提供朝着这个方向发展的 Try。

但在书中和课程中,Martin Odersky 似乎并没有(至少现在)说异常是不好的,而且他经常使用它们。 我还注意到方法断言/要求...

最后我有点困惑,因为我想遵循最佳实践,但它们不清楚,而且语言似乎是双向的......

有人可以解释一下在这种情况下我应该使用什么吗?


基本准则是对真正异常的事情使用异常**。对于“普通”故障,最好使用Option or Either。如果您正在与 Java 进行交互,当有人以错误的方式打喷嚏时会抛出异常,您可以使用Try确保自己的安全。

让我们举一些例子。

假设您有一个从地图中获取某些内容的方法。可能会出什么问题?嗯,一些戏剧性和危险的事情,比如 segfault* 堆栈溢出,或者一些预期的事情,比如找不到元素。您可以让 segfault 堆栈溢出抛出异常,但如果您只是找不到元素,为什么不返回一个Option[V]而不是值或异常(或null)?

现在假设您正在编写一个程序,用户应该在其中输入文件名。现在,如果您不打算在出现问题时立即退出该计划,Either是要走的路:

def main(args: Array[String]) {
  val f = {
    if (args.length < 1) Left("No filename given")
    else {
      val file = new File(args(0))
      if (!file.exists) Left("File does not exist: "+args(0))
      else Right(file)
    }
  }
  // ...
}

现在假设您想要解析一个以空格分隔的数字的字符串。

val numbers = "1 2 3 fish 5 6"      // Uh-oh
// numbers.split(" ").map(_.toInt)  <- will throw exception!
val tried = numbers.split(" ").map(s => Try(s.toInt))  // Caught it!
val good = tried.collect{ case Success(n) => n }

因此,您(至少)有三种方法来处理不同类型的故障:Option因为它有效/无效,在不工作是预期行为的情况下,而不是令人震惊和令人震惊的失败;Either当事情可以工作或不工作时(或者,实际上,您有两个相互排斥的选项的任何情况)并且您想要保存一些有关出错原因的信息;和Try当您不想自己处理令人头疼的异常处理,但仍需要与支持异常的代码进行交互时。

顺便说一句,例外是很好的例子——所以你会在教科书或学习材料中比在其他地方更常见地发现它们,我认为:教科书的例子往往是不完整的,这意味着通常可以通过仔细设计来避免的严重问题应该相反,通过抛出异常来进行标记。

*Edit: Segfaults crash the JVM and should never happen regardless of the bytecode; even an exception won't help you then. I meant stack overflow.

**Edit: Exceptions (without a stack trace) are also used for control flow in Scala--they're actually quite an efficient mechanism, and they enable things like library-defined break statements and a return that returns from your method even though the control has actually passed into one or more closures. Mostly, you shouldn't worry about this yourself, except to realize that catching all Throwables is not such a super idea since you might catch one of these control flow exceptions by mistake.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Scala 中抛出异常,什么是“官方规则” 的相关文章

随机推荐

  • 如何将数组与 setState 一起使用?

    我目前正在使用以下命令将数组映射到 setState 但没有设置任何内容 也没有记录任何错误 如果我明确地逐行写出它 它就会起作用 关于如何解决这个问题有什么想法或建议吗 使用数组设置状态 不设置状态 const myData messag
  • Net core EF 3.1 LINQ 字符串比较不再起作用

    我有以下课程 public class Employee public string Name get set 以及 EF Core 2 1 中的 LINQ 查询 Employee GetEmployeeByName string name
  • 有没有办法在没有 QApplication::exec() 的情况下使用 Qt?

    有没有一种安全的方法可以在不调用 QApplication exec 的情况下使用 Qt 我有许多不同的对象正在对多个资源执行长期进程 至少其中一个正在与 Web 应用程序服务器进行通信 我正在制作一个 GUI 应用程序 提示用户在正确的时
  • 阻止 div 容器调整大小

    我的 html 页面中有两列 一列向右浮动 另一列向左浮动 我已将两个容器的高度设置为 100 将两个容器的宽度设置为 50 我希望这两个容器适合中间的窗户 当用户水平调整窗口大小时 我不希望内容调整大小 我怎样才能做到这一点 Thanks
  • Android Activity 旋转刷新

    我是一名经验丰富的 NET 开发人员 但这是我的第一个 Android 应用程序 它让我发疯 这是一个运行良好的倒计时器 但是当您旋转屏幕时 它会重新初始化归零并停止倒计时的活动 这就是我尝试过的 我摆脱了 CountDownTimer 对
  • 如何处理剪贴板阻塞和其他异常情况

    在过去的几个小时中 我一直在追踪一个相当具体的错误 该错误是由于另一个应用程序打开了剪贴板而发生的 本质上 由于剪贴板是共享资源 根据 为什么我的共享剪贴板不起作用 http blogs msdn com rds archive 2006
  • Ruby 中的 Set 是否始终保留插入顺序?

    即 Ruby 的 Set 相当于 Java 的 LinkedHashSet 吗 在 Ruby 1 9 中 yes 在 Ruby 1 8 中 可能不会 Set uses a Hash内部 https github com ruby ruby
  • 常规请求期间 Django AJAX 请求未通过

    我有一个带有登录网页的 Django 站点 当提交页面上的登录表单时 它会执行登录视图 该视图会在其中运行一个需要很长时间处理 30秒左右 的函数 因此 为了在登录期间向客户端显示进度 一旦提交表单 登录页面上的 JS 函数就会开始向服务器
  • 创建新的 Eclipse 插件项目时何时选择“生成激活器...”

    有很多 Eclipse RCP 教程都从明显的第一步开始 创建一个新的插件项目 看来大约 其中 70 指定检查 生成一个激活器 一个控制插件生命周期的Java类 其他人特别说不要检查该切换 替代文本http img179 imageshac
  • WordPress 计划事件未在设定时间触发

    在 WordPress 中 我正在创建一个插件 用于向用户发送电子邮件 为此 我使用 WordPresscron工作 所以基本上它要做的就是每小时向用户发送电子邮件 所以我的代码看起来像这样 public function construc
  • MVC3、Ninject、MvcSiteMapProvider - 如何将依赖项注入到重写方法

    我有一个正在使用的 MVC3 应用程序Ninject http ninject org and Mvc站点地图提供者 http mvcsitemap codeplex com 我创建了此类 MvcSiteMapProvider 使用它来动态
  • 如何在 Angular2 中实现间隔/轮询以与量角器一起使用?

    我有一个 angular2 应用程序 我想用量角器进行测试 在此应用程序中 我有一个带有图表的页面 该页面正在使用自动生成的数据定期更新 显然 Protractor 的一项功能是在执行测试代码之前等待脚本和 http 调用完成 但是 如果有
  • 将现有表单添加到 C++/CLI WinForms 项目

    我在不同的解决方案中有两个 C CLI 项目 A 和 B 我使用 A 进行实验 测试 并在完成测试后将测试的代码移至 B 但是 我发现在将 Windows 窗体类 标头 cpp 和 resx 添加到项目 B 时 我无法再使用 IDE 的可视
  • 将 Cookie 从 CookieContainer 写入 IE Cookie 存储

    我想从桌面应用程序导航到 Web 应用程序中的页面 没问题 我听到你说 只需使用正确的 URL 启动默认浏览器即可 但是 Web 应用程序使用 ASP NET 表单身份验证 用户不想看到登录页面 因为他们已经在桌面应用程序中使用相同的凭据进
  • 如何在 REST WCF 服务中接受任意 JSON 对象?

    我想实现这样的服务方法 OperationContract WebInvoke RequestFormat WebMessageFormat Json ResponseFormat WebMessageFormat Json public
  • 在高频交易中尝试并行订单处理是否有意义?

    好吧 我认为对于那些熟悉 hft 的人来说 这是一个更理论的问题 我收到来自 FAST 的订单并进行处理 我每秒收到大约 2 3 千个订单 问题是我是否应该尝试同步或异步处理它们 每次收到下一个订单时 我都需要执行以下操作 更新相应工具的订
  • 是否可以在两个应用程序之间共享一项应用程序内购买?

    我的产品有两种不同的版本 一种用于 iPhone 另一种用于 iPad 是否有可能解锁功能通过应用内购买in both与其中之一一起玩一次 您不能使用相同的 ID 但是 您可以管理有关哪些用户在您自己的服务器上进行了哪些购买的信息 并在用户
  • Python 脚本在开机时启动

    我正在制作一个简单的 python 脚本作为在后台运行的可执行文件运行 有没有办法让它在启动时运行 我知道我可以将可执行文件添加到启动目录 但这需要我根据我的机器对其进行硬编码 我希望它也能在其他机器上运行 Windows 和 ubuntu
  • 在不丢失基数信息的情况下对 TensorFlow 数据集进行窗口处理?

    tf data Dataset window返回一个新的数据集 其元素是数据集 这些嵌套数据集的元素是所需大小的窗口 如果您有一个数据集 例如 Dataset range 10 并想要一个像这样的窗口数据集 0 1 2 1 2 3 7 8
  • Scala 中抛出异常,什么是“官方规则”

    我正在 Coursera 上学习 Scala 课程 我也开始阅读 Odersky 的 Scala 书 我经常听到的是 在函数式语言中抛出异常不是一个好主意 因为它破坏了控制流 并且我们通常返回一个失败或成功的 Either Scala 2