当前位置: 首页 > 知识库问答 >
问题:

我为什么要使用发散函数?

陈高寒
2023-03-14

通读Rust这本书,我遇到了一个有趣的话题——发散函数:

Rust对“发散函数”有一些特殊的语法,这些函数不会返回:

fn diverges() -> ! {
    panic!("This function never returns!");
}

发散函数可以用作任何类型:

let x: i32 = diverges();
let x: String = diverges();

发散函数的用例是什么?书上说

惊慌失措!()导致当前执行线程因给定消息而崩溃。因为这个函数会导致崩溃,它永远不会返回,所以它的类型是

这是有道理的,但我想不出发散函数还有什么用处,它似乎非常局限于恐慌 。我知道一定有一些有用的场景,解释为什么它们引入了发散函数。在Rust中,我可能在哪里看到不同的函数?


共有3个答案

应和悦
2023-03-14

最常见的用例之一是在#中启用(自定义)恐慌![no_std]环境:

#![panic_handler]
fn panic(_info: &PanicInfo) -> ! {
    loop{}
}

您将在Philip Oppermann的Rust OS开发教程中看到许多不同的功能,因为当您在如此低的级别工作时,返回会导致CPU出现三重故障并使其重置(或者用外行的话来说,导致立即重新启动)。

全彬
2023-03-14
匿名用户

正如您在书中引用的,Rust的底部类型用于指定不返回的函数。这包括:

  • 惊慌失措!()

魏健柏
2023-03-14
匿名用户

它有几个用途。它可以用于设计为死机或退出程序的功能<代码>恐慌!()本身就是这样一个函数,但它也可以应用于包装恐慌的函数!(),例如打印出更详细的错误信息,然后惊慌失措。

它也可以用于从不返回的函数。如果一个函数进入无限循环,例如服务器的主循环,因此永远不会返回,则可以这样定义。

另一个可能的用途是围绕Unixexec函数系列的包装器,其中当前进程将替换为正在执行的进程。

拥有这样一个类型很有用,因为它与所有其他类型兼容。为了确保类型安全,Rust必须确保语句的所有分支都匹配if语句返回相同的类型。但如果有一些分支无法访问或指示错误,则需要某种方法抛出一个错误,该错误将与其他分支返回的类型统一。因为与所有类型统一,可用于任何此类情况。

目前有一个有趣的RFC(和讨论)主张(部分)扩展可以使用的地方,认为它应该被视为成熟的类型,如()is;是一种没有与所有其他类型统一的值的类型,而()是一种具有单个值的不同类型。我不确定我是否同意完整的RFC,但将视为成熟类型的讨论很有趣,我认为可以与RFC的其余部分分开提出。

更新:由于我写了以上内容,RFC中关于推广的部分 到一个成熟的类型被拆分成一个单独的RFC并合并,并且正在实施中(目前在功能门后面的夜间版本中可用)。作为一个成熟的类型,它可以在更多的上下文中使用,例如在Result中

 类似资料:
  • 本文向大家介绍为什么要用纯函数?相关面试题,主要包含被问及为什么要用纯函数?时的应答技巧和注意事项,需要的朋友参考一下 在此之前要先了解什么是纯函数,简单来说纯函数的定义有两个: 1.返回的结果只依赖于传入的参数。 2.执行过程中不产生副作用。 在这里就需要了解到什么是副作用 1.改变了外部变量或者对象属性 2.触发任何外部进程 3.发送http请求 4.调用其他有副作用的函数 5.…… 那么我们

  • 问题内容: 基数实际上是什么意思?我们为什么需要它? 问题答案: 您可能并不总是希望将整数解析为以10为底的数字,因此提供基数可以指定其他数字系统。 基数是一位数字的值数。十六进制为16。八进制为8,二进制为2,依此类推… 在该函数中,您可以执行一些操作来提示基数而不提供基数。如果用户输入的字符串与其中一个规则匹配,但没有明确规定,则这些方法也可能对您不利。例如:

  • 问题内容: 我正在尝试使用此命令安装Python软件包 我收到权限错误,不确定为什么。我可以使用来运行它,但是有人告诉我这是个坏主意,我应该改用virtualenv。 什么是虚拟环境?它对我有什么作用? 问题答案: 与系统Python和库一起运行会将您限制为OS提供商选择的一个特定Python版本。试图在一个Python安装上运行所有Python应用程序,可能会导致库集合之间发生版本冲突。对系统P

  • 问题内容: 我开始使用RxJS,但我不明白为什么在此示例中我们需要使用类似or 的函数;数组的数组在哪里? 如果有人可以直观地解释正在发生的事情,那将非常有帮助。 问题答案: 当您有一个Observable的结果是更多Observable时,可以使用flatMap。 如果您有一个由另一个可观察对象产生的可观察对象,则您不能直接过滤,缩小或映射它,因为您有一个可观察对象而不是数据。如果您生成一个可观

  • 问题内容: 我有一个将对象保存到数据库的EJB。在我看到的一个示例中,一旦保存了此数据(EntityManager.persist),就会调用EntityManager.flush();。为什么我需要这样做?我要保存的对象未附加,以后在该方法中也不会使用。实际上,一旦保存,该方法就会返回,并且我希望资源会被释放。(示例代码也在remove调用上执行此操作。) 问题答案: 调用将强制数据立即被持久保

  • 我看到一个例子,其中有一个员工列表(表格)和他们各自的月薪。我查了一下工资,在工资中看到了完全相同的表格。这很奇怪。 这是必须要做的事情——我们必须弄清楚这个月我们支付了多少工资。为此,我们需要在数据库中合计他们的工资金额,如下所示: 我知道如果我没有在上面的代码中使用< code>GROUP BY,我会得到一个错误。这就是我不明白的地方。 我们正在从员工表中选择员工ID。被告知它必须从员工表中添