Rust从入门到实战系列二百三十二:从不返回的 never type

本文介绍了Rust语言中的nevertype(空类型),用于表示函数不会返回的情况,以及它在match表达式、panic!、Option::unwrap和循环结构中的应用。讨论了continue的非返回值特性,以及nevertype如何强转为其他类型。
摘要由CSDN通过智能技术生成

Rust 有一个叫做 ! 的特殊类型。在类型理论术语中,它被称为 empty type,因为它没有值。我们更倾向
于称之为 never type。这个名字描述了它的作用:在函数从不返回的时候充当返回值。例如:
fn bar() -> ! {
// --snip–

panic!();

}
这读 ” 函数 bar 从不返回”,而从不返回的函数被称为 发散函数(diverging functions)。不能创建 ! 类型
的值,所以 bar 也不可能返回值。
不过一个不能创建值的类型有什么用呢?如果你回想一下示例 2-5 中的代码,曾经有一些看起来像这样
的代码,如示例 19-26 所重现的:

use rand::Rng;

use std::cmp::Ordering;

use std::io;

19.3. 高级类型 507

fn main() {

println!(“Guess the number!”);

let secret_number = rand::thread_rng().gen_range(1…101);

println!(“The secret number is: {}”, secret_number);

loop {

println!(“Please input your guess.”);

let mut guess = String::new();

// --snip–

io::stdin()

.read_line(&mut guess)

.expect(“Failed to read line”);

let guess: u32 = match guess.trim().parse() {
Ok(num) => num,
Err(_) => continue,
};

println!(“You guessed: {}”, guess);

// --snip–

match guess.cmp(&secret_number) {

Ordering::Less => println!(“Too small!”),

Ordering::Greater => println!(“Too big!”),

Ordering::Equal => {

println!(“You win!”);

break;

}

}

}

}

示例 19-26: match 语句和一个以 continue 结束的分支
当时我们忽略了代码中的一些细节。在第六章 ”match 控制流运算符” 部分,我们学习了 match 的分支
必须返回相同的类型。如下代码不能工作:

fn main() {

let guess = “3”;

let guess = match guess.trim().parse() {
Ok() => 5,
Err(
) => “hello”,
};

}

这里的 guess 必须既是整型 也是字符串,而 Rust 要求 guess 只能是一个类型。那么 continue 返回了
什么呢?为什么示例 19-26 中会允许一个分支返回 u32 而另一个分支却以 continue 结束呢?
正如你可能猜到的,continue 的值是 !。也就是说,当 Rust 要计算 guess 的类型时,它查看这两个分
支。前者是 u32 值,而后者是 ! 值。因为 ! 并没有一个值,Rust 决定 guess 的类型是 u32。
描述 ! 的行为的正式方式是 never type 可以强转为任何其他类型。允许 match 的分支以 continue 结束
508 CHAPTER 19. 高级特征
是因为 continue 并不真正返回一个值;相反它把控制权交回上层循环,所以在 Err 的情况,事实上并未
对 guess 赋值。
never type 的另一个用途是 panic!。还记得 Option 上的 unwrap 函数吗?它产生一个值或 panic。
这里是它的定义:

enum Option {

Some(T),

None,

}

use crate::Option:😗;

impl Option {
pub fn unwrap(self) -> T {
match self {
Some(val) => val,
None => panic!(“called Option::unwrap() on a None value”),
}
}
}
这里与示例 19-34 中的 match 发生了相同的情况:Rust 知道 val 是 T 类型,panic! 是 ! 类型,所以整
个 match 表达式的结果是 T 类型。这能工作是因为 panic! 并不产生一个值;它会终止程序。对于 None
的情况,unwrap 并不返回一个值,所以这些代码是有效的。
最后一个有着 ! 类型的表达式是 loop:

fn main() {

print!("forever ");
loop {
print!("and ever ");
}

}

这里,循环永远也不结束,所以此表达式的值是 !。但是如果引入 break 这就不为真了,因为循环在执
行到 break 后就会终止。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值