为什么我会使用不同的功能?

Syn*_*ose 27 rust

通过Rust书阅读,我遇到了一个有趣的话题 - 不同的功能:

Rust有一些特殊的'分叉函数'语法,这些函数不返回:

fn diverges() -> ! {
    panic!("This function never returns!");
}
Run Code Online (Sandbox Code Playgroud)

发散功能可以用作任何类型:

let x: i32 = diverges();
let x: String = diverges();
Run Code Online (Sandbox Code Playgroud)

发散功能的用例是什么?这本书说的

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

这是有道理的,但我不能想到一个不同的功能将在哪里使用,它似乎非常本地化panic!.我知道必须有一些有用的场景,为什么他们引入了不同的功能.在Rust哪里可能会看到不同的功能?

Bri*_*ell 37

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

它也可以用于永不返回的功能.如果函数进入无限循环,例如服务器的主循环,因此永远不会返回,则可以通过这种方式定义.

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

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

目前有一个有趣的RFC(和讨论)争论(部分)扩展!可以使用的地方,认为它应该被视为完全成熟的类型,如(); !是一种没有与所有其他类型统一的值的类型,()而是具有单个值的不同类型.我不确定我是否同意完整的RFC,但是对于!作为一个完整类型进行处理的讨论很有意思,我认为可以与RFC的其余部分分开提出.

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


mdu*_*dup 13

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

  • panic!()
  • 永远循环
  • 退出程序(除了返回main()),例如exit(),其签名是pub fn exit(code: i32) -> !

  • 我最喜欢的是`未实现的!()`和`无法访问!()`. (4认同)