编程语言中错误处理机制的思考

当我们编写代码时,在调用其他函数时,函数内部会发生错误:

fn f() {
// Error can happen when b()
// returns an errora = b()...
}

由此产生的问题是:

  • 有时我们不想处理错误,只是从函数返回
  • 有时候我们想减轻错误
  • 有时候我们希望更晚处理错误-例如,处理其他错误。优选地,正常控制流继续。

每种编程语言都找到了不同的解决方案来应对这三个挑战。

Java 是第一批通过 Exceptions 提升到更高错误管理状态的大众语言之一。 b() 可以在错误时抛出异常。然后调用函数什么也不能做,在这种情况下,调用函数 f() 返回给它的调用者,并带有异常。或者它可以稍后通过将调用包装在try/catch 中来处理异常。Java 方法的缺点是在错误发生后我们不能有正常的控制流。要么我们处理,要么让它冒出来。

Java 异常机制的缺点之一是声明已检查的异常。如果我们的函数 f() 声明了它的异常,而函数 b() 抛出了不同的异常,我们需要以任何一种方式处理异常,因为它不会冒泡。

Rust 找到了一个解决方案,它有一种机制,可以自动将一个错误( b() )转换为另一个错误( f() )。这样我们就可以让错误冒出来而不处理它。Rust 使用 ? 符号:

fn f() {// Let function f() return// error autoconvert and bubble upa = b()?...
}

一些编程语言通过在值旁边返回错误代码来处理这三个挑战。其中之一就是 Go :

a, err := b()

现在我们可以处理错误了

if err != nil { .... }

或者从我们的函数返回。我们可以在错误发生后有正常的程序流程-在错误情况下-除非我们想对一个操作:

a = a + 1

如果有错误并且 a 为nil,则不工作。

我们现在可以每次检查 a 的存在:

if a != nil { .... }

但这变得麻烦且快速不可读。

一些编程语言使用 Monads 处理错误后的控制流问题。

// a is of type Result<A,E>
a = b()

有了 Result Monad,我就可以处理方法的错误或返回。如上所述,对于返回 Rust 有一些特殊的语法:

a = b()?带问号,函数将在 `b()` 返回错误时返回该行,并且错误会随着自动转换而冒泡。

我们也可以在错误的情况下使用正常的控制流,但仍然使用 a. 魔法!

a = b()
c = a.map(|v| v + 1)...
// Deal with error later

在错误的情况下, c 也将是错误,否则 c 将包含 a 的值加1。这样,无论错误发生与否,我们都可以在错误发生后拥有相同的控制流。

这使得代码的推理更加容易。

Zig 通过用 ! 注释类型,有一个简短的 Result<A,E> 概念。

// Returns i32
fn f() i32 {
...
}// Returns i32 or an error
fn f() !i32 {
...
}

Zig 还解决了 Java 中通过流分析声明异常的繁琐问题。它会检查你的函数 f() 并找出它可以返回的所有错误。然后,如果您检查调用代码中的特定错误,它会确保它是详尽的。

带有 ? 的 Rust 有一个特殊的语法来当场返回。Java 有特殊的语法 try/catch ,如果我们不写额外的代码,就不会当场返回并返回给函数的调用者。

问题是:我们经常做什么?返回错误或继续?我们经常使用的,应该有较少冗长的语法。对于 Rust 中的 ? case,我们应该需要一个 ? 来返回,还是需要一个 ? 来不返回?

a = b()?

? 可以表示“错误返回”。或者行为可以是,如果 b() 返回一个错误,而 ? 阻止了这个错误,那么总是当场返回。

这取决于发生的更频繁。

Golang可能会给予我们另一条线索。当函数返回时,它有特殊的清理语法:

f := File.open("my.txt")
// Make sure we close the file
// on exiting the function
defer f.close()a, err = b()if err != nil {// f.close() is called herereturn
}

Java 有一些不那么优雅的东西。看起来人们认为错误应该冒出来,在这种情况下,我们需要一些简单的清理。

从我的经验来看,我也怀疑我们会希望让大多数错误通过自动转换而出现,所以 ? 可能应该表示我们不希望函数返回,这与 Rust 正在做的相反。

Java 似乎是正确的,例外。没有语法意味着泡沫行为。它错过了自动转换和来自 Rust 的 Exception<V,E> ,以及一个本地的,简单的 defer ,如 Go,而不是非本地的,冗长的 Java 中 finally 。Java 没有解释如何正确使用异常,所以每个人都以错误的方式使用异常。

那么,一个假设的语言,像这样:

fn f() {// b() returns Result<V,E> or !V in Zig,// f() returns if b is an error// a is of type Va = b()// do not return on error but// a is of type Result<V,E> or !Va = b()!// compiles to a = a.map(|v| v + 1)a = a + 1// compiles to c = a.map(|v| v.c())// c is of type Result<C,E>c = a.c()...
}

这具有更高的可读性。

当调用另一个方法时,我们应该怎么做?

// Does not work if d expects
// C as a parameter type
// and not Result<C,E>
d(c)

有些语言有一个特殊的语言语法来处理这个问题。Haskell 有 do ,Scala 有 for 但是你有特殊的代码围绕错误和特殊的上下文。这使得事情更难再读一遍,与本意相反。

所以最好抛出编译器错误。请记住,默认的方式是向上冒泡,并且 a 的类型是 V 。

我们可以通过控制流分析来减轻痛苦。一些编程语言,如 TypeScript,做的是这样的事情:

a = b()
a = a + 1 // A is still Result<V,E>
if a instanceof Error {return
}
// A is now of type V
// because we checked for an error
d(a)

看起来每种编程语言都有一个最佳错误处理难题。从我所看到的,没有人成功过。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/48260.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于SpringBoot+Vue的校园台球厅设备管理系统(带1w+文档)

基于SpringBootVue的校园台球厅设备管理系统(带1w文档) 基于SpringBootVue的校园台球厅设备管理系统(带1w文档) 本次设计任务是要设计一个校园台球厅人员与设备管理系统&#xff0c;这个系统能够满足校园台球厅人员与设备的管理及用户的校园台球厅人员与设备管理功能。系统的主…

彻底卸载360安全卫士的方法

法一&#xff1a; 按下WindowsR键&#xff0c;并输入msconfig, 在“引导”选项卡中选择“安全引导”&#xff0c;并重新启动进入安全模式。此时&#xff0c;重复第一种方法“应用和功能”-“360安全卫士”-“卸载”&#xff0c;在弹出的对话框中残忍的拒绝它的各种令人发指的无…

go-微服务的设计概括

一、微服务到底是什么&#xff1f; 初学者很容易把微服务和分布式混为一谈&#xff0c;但其实二者之间存在非常大的差异&#xff0c;我个人认为主要有以下几点&#xff1a; 分布式主要是一种技术手段&#xff0c;用来保证多个相同的进程能够共同工作而不出错。采用各种复杂的…

Window任务栏应用图片无法加载解决方法

在Windows系统中&#xff0c;如果任务栏应用图标显示成白色方块&#xff0c;可能是由于图标缓存文件损坏或者显示设置错误导致的。以下是一些解决方法&#xff1a; 重新启动Windows资源管理器&#xff1a; 按下Ctrl Shift Esc组合键打开任务管理器。在“进程”标签页中找到…

2024-07-19 Unity插件 Odin Serializer1 —— 插件介绍

文章目录 1 介绍2 拓展序列化类3 学习目的 1 介绍 ​ Odin Serializer 是 Unity 的一个插件&#xff0c;其主要用途是扩展 Unity 现有的序列化&#xff08;如 MonoBehaviour 或 ScriptableObject 类&#xff09;&#xff0c;并可以独立于 Unity 类使用 Odin Serializer。 ​ …

桌面应用打开默认全屏功能

1.修改package.json 在main属性上面引入新的html页面 {"main": "/index.html","name": "phadcloud","description": "名称","version": "1.0","keywords": ["名称"],&…

基于Ubuntu2310搭建openstack高可用集群B版

openstack-ha 环境初始化安装haproxy安装keepalived数据库集群高可用rabbitmq集群高可用memcache集群配置 keystone高可用glance高可用placement高可用nova高可用neutron高可用horizon高可用 本实验使用两台节点master和node配置haproxy高可用&#xff0c;keepliaved配置主备抢…

IntelliJ IDEA 直接在软件中更新为最新版

当我们的 IDEA 工具许久没有更新&#xff0c;已经拖了好几个版本&#xff0c;想跨大版本更新&#xff0c;比如从2020.2.1 -> 2023.x.x 此时&#xff0c;我们菜单栏点击 Help -> Check for Updates… &#xff0c;右下角会有提示更新&#xff0c;如下图&#xff1a; 点…

leetcode位运算(3211. 生成不含相邻零的二进制字符串)

前言 经过前期的基础训练以及部分实战练习&#xff0c;粗略掌握了各种题型的解题思路。接下来重点专项练习&#xff0c;加强重难点知识的练习。 描述 给你一个正整数 n。 如果一个二进制字符串 x 的所有长度为 2 的 子字符串 中包含 至少 一个 "1"&#xff0c;则称…

go 实现websocket以及详细设计流程过程,确保通俗易懂

websocket简介&#xff1a; WebSocket 是一种网络传输协议&#xff0c;可在单个 TCP 连接上进行全双工通信&#xff0c;位于 OSI 模型的应用层。WebSocket 协议在 2011 年由 IETF 标准化为 RFC 6455&#xff0c;后由 RFC 7936 补充规范。 WebSocket 使得客户端和服务器之间的数…

Python PDF Magic:合并和拆分随心所欲

大家好&#xff01;小编今天要为大家带来一篇关于Python操作PDF的秘籍——无论是要将PDF合并成一份整体&#xff0c;还是将一个庞大的PDF文件拆分成多个小伙伴&#xff0c;都轻松hold住&#xff01;你准备好了吗&#xff1f;让我们开始这场奇妙的PDF操作之旅吧&#xff01; 准…

机械学习—零基础学习日志(高数06——函数特性)

零基础为了学人工智能&#xff0c;真的开始复习高数 函数的性质&#xff0c;开始新的学习&#xff01; 有界性&#xff1a; 解法放这里&#xff1a; 证明有界&#xff0c;其实内部的包含知识点很多。第一&#xff0c;如果有界&#xff0c;你需要证明函数在一定区间内&#xff…

《Techporters架构搭建》-Day02 集成Mybatis-plus

集成Mybatis-plus Mybatis-plus集成Mybatis-plus步骤小结 Mybatis-plus Mybatis-plus官网 MyBatisPlus&#xff08;简称MP&#xff09;是一个MyBatis的增强工具&#xff0c;在MyBatis的基础上只做增强不做改变&#xff0c;为简化开发、提高效率而生。它引入了一些新的特性&…

微信小程序:API 进行Promise化

小程序 API 进行Promise化 安装 miniprogram-api-promise1.0.4 npm install --save miniprogram-api-promise1.0.4yarn add miniprogram-api-promise1.0.4在 app.js 中调用 promisifyAll() 方法。 // 实现异步 API Promise 化 import { promisifyAll } from miniprogram-api-pr…

【探索Linux】P.40(传输层 —— TCP滑动窗口 | 快重传 | 流量控制 )

阅读导航 引言一、TCP滑动窗口1. 为什么要用滑动窗口&#xff08;1&#xff09;逐个确认&#xff08;2&#xff09;优化逐个确认&#xff08;滑动窗口&#xff09; 2. TCP滑动窗口的工作原理 二、快重传的引入三、快速重传详细介绍1. 机制原理2. 触发条件3. 操作步骤4. 与超时重…

如何处理AI模型中的“Gradient Vanishing”错误:优化训练技巧

如何处理AI模型中的“Gradient Vanishing”错误&#xff1a;优化训练技巧 &#x1f311; 如何处理AI模型中的“Gradient Vanishing”错误&#xff1a;优化训练技巧 &#x1f311;摘要引言“Gradient Vanishing”问题的成因分析 &#x1f914;1. 激活函数的选择2. 网络层数过深3…

Python补充前文未述知识

函数名说明 chr(x) 将对应的字符转换为ASCII编码&#xff0c;也可以将整数x转换为一个字符ord(x)将对应的字符转换为unicode编码&#xff08;包括中文&#xff09;bin(x)将一个整数x转换为一个二进制字符串oct(x)将一个整数x转换为一个八进制字符串hex(x)将一个整数x转换为一个…

【自动驾驶汽车通讯协议】SPI通讯:深入理解与应用

文章目录 0. 前言1. 工作原理2. 模式与配置2.1 CPOL (Clock Polarity)2.2 CPHA (Clock Phase)2.3 组合模式 3. 特性与优势4. 在自动驾驶汽车中的应用5. 结论 0. 前言 按照国际惯例&#xff0c;首先声明&#xff1a;本文只是我自己学习的理解&#xff0c;虽然参考了他人的宝贵见…

Linux 之 awk命令详解

Linux命令详解&#xff1a;巧妙使用awk命令进行文本处理 基本用法 常用功能 1. 打印指定列 2. 使用分隔符 3. 条件过滤 4. 格式化输出 高级功能 1. 使用BEGIN和END块 2. 内置变量 3. 自定义函数 实战案例 总结 Linux命令详解&#xff1a;巧妙使用awk命令进行文本处…

力扣 217. 存在重复元素,389. 找不同,705. 设计哈希集合,3. 无重复字符的最长子串,139. 单词拆分

217. 存在重复元素 题目 给你一个整数数组 nums 。如果任一值在数组中出现 至少两次 &#xff0c;返回 true &#xff1b;如果数组中每个元素互不相同&#xff0c;返回 false 。 AC代码 class Solution { public:bool containsDuplicate(vector<int>& nums) {// …