为什么要使用发散函数? [英] Why would I use divergent functions?

查看:32
本文介绍了为什么要使用发散函数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

<块引用>

Rust 有一些特殊的发散函数"语法,它们是不返回的函数:

fn diverges() ->!{panic!("这个函数永远不会返回!");}

<块引用>

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

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

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

<块引用>

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

这是有道理的,但我想不出还有什么地方可以使用发散函数,而且它似乎非常本地化为只是 panic!.我知道一定有一些有用的场景可以解释为什么他们引入了不同的功能.我可能会在哪里看到 Rust 中的不同功能?

解决方案

它有多种用途.它可用于旨在恐慌或退出程序的功能.panic!() 本身就是一个这样的函数,但是它也可以应用于包装panic!()的函数,比如打印出更详细的错误信息然后panic.

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

另一种可能的用途是围绕 Unix exec函数族,其中当前进程替换为正在执行的进程.

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

有一个有趣的(和一个 href="https://github.com/rust-lang/rfcs/pull/1154" rel="noreferrer">讨论) 目前(部分)为 扩展可以使用的地方!/a>,认为它应该被视为一个完整的类型,就像 () 是;! 是一种没有值的类型,与所有其他类型统一,而 () 是一种具有单个值的不同类型.我不确定我是否同意完整的 RFC,但将 ! 视为成熟类型的讨论很有趣,我认为可以与 RFC 的其余部分分开提出.

更新:由于我写了上面的内容,RFC 中关于将 ! 提升为成熟类型的部分是 拆分为单独的 RFC 并合并,并且是 正在实施中(目前在功能门后面的夜间构建中可用).作为一个成熟的类型,它可以用在更多的上下文中,例如在 Result 中表示永远不会失败的结果,或者 Result 作为一个永远不会成功的人.这些在通用上下文中很有用;如果你有一些 trait 需要一个方法来返回结果,但对于那个特定的实现它只能成功,你不需要填写一些虚拟错误类型.

Reading through the Rust book, I came across an interesting topic — divergent functions:

Rust has some special syntax for ‘diverging functions’, which are functions that do not return:

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

A diverging function can be used as any type:

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

What would be the use cases of a divergent function? The book says that

panic!() causes the current thread of execution to crash with the given message. Because this function will cause a crash, it will never return, and so it has the type !

That makes sense, but I can't think of where else a divergent function would be of use and it seems very localized to just panic!. I know there must be some useful scenarios out there for why they introduced divergent functions. Where would I likely see divergent functions in Rust?

解决方案

It has several uses. It can be used for functions which are designed to panic or exit the program. panic!() itself is one such function, but it can also be applied to functions which wrap panic!(), such as printing out more detailed error information and then panicking.

It can also be used for functions that never return. If a function goes into an infinite loop, such as the main loop of a server, and thus never returns, it could be defined this way.

Another possible use would be a wrapper around the Unix exec family of functions, in which the current process is replaced with the one being executed.

It is useful to have such a type because it is compatible with all other types. In order to be type safe, Rust has to ensure that all branches of a match or if statement return the same type. But if there are some branches that are unreachable or indicate an error, you need some way to throw an error that will unify with the type returned by the other branches. Because ! unifies with all types, it can be used in any such case.

There is an interesting RFC (and discussion) at the moment that argues (in part) for expanding the places where ! can be used, arguing that it should be treated as a full fledged type like () is; ! being a type with no values that unifies with all other types, while () being a distinct type with a single value. I'm not sure I agree with the full RFC, but the discussion of treating ! as a full-fledged type is interesting and I think could be proposed separately from the rest of the RFC.

Update: Since I wrote the above, the part of the RFC about promoting ! to a full fledged type was split into a separate RFC and merged, and is in the process of being implemented (currently available in nightly builds behind a feature gate). As a full-fledged type, it can be used in more contexts, such as in Result<T, !> indicating a result that can never fail, or Result<!, E> as one that can never succeed. These are useful in generic contexts; if you have some trait that requires a method to return a result, but for that particular implementation it can only possibly succeed, you don't need to fill in some dummy error type.

这篇关于为什么要使用发散函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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