Rust从入门到实战系列二百一十:函数参数

本文介绍了Rust语言中函数参数如何使用模式,特别是元组解构,并区分了不可反驳模式(如let中的匹配)和可反驳模式(如iflet中的可能失败处理)。作者通过示例展示了在不同上下文中正确使用这两种模式的重要性,并提供了相应的编译时错误和解决方案。
摘要由CSDN通过智能技术生成

函数参数也可以是模式。列表 18-6 中的代码声明了一个叫做 foo 的函数,它获取一个 i32 类型的参数 x,
现在这看起来应该很熟悉:
fn foo(x: i32) {
// code goes here
}

fn main() {}

列表 18-6: 在参数中使用模式的函数签名
x 部分就是一个模式!类似于之前对 let 所做的,可以在函数参数中匹配元组。列表 18-7 将传递给函数
的元组拆分为值:
文件名: src∕main.rs
fn print_coordinates(&(x, y): &(i32, i32)) {
println!(“Current location: ({}, {})”, x, y);
}
fn main() {
let point = (3, 5);
print_coordinates(&point);
}
一个在参数中解构元组的函数
这会打印出 Current location: (3, 5)。值 &(3, 5) 会匹配模式 &(x, y),如此 x 得到了值 3,而 y得到了值 5。
因为如第十三章所讲闭包类似于函数,也可以在闭包参数列表中使用模式。
现在我们见过了很多使用模式的方式了,不过模式在每个使用它的地方并不以相同的方式工作;在一些
地方,模式必须是 irrefutable 的,意味着他们必须匹配所提供的任何值。在另一些情况,他们则可以是
refutable 的。接下来让我们讨论这两个概念。
Refutability(可反驳性): 模式是否会匹配失效
ch18-02-refutability.md
commit d44317c3122b44fb713aba66cc295dee3453b24b
模式有两种形式:refutable(可反驳的)和 irrefutable(不可反驳的)。能匹配任何传递的可能值的模式
被称为是 不可反驳的(irrefutable)。一个例子就是 let x = 5; 语句中的 x,因为 x 可以匹配任何值所以
不可能会失败。对某些可能的值进行匹配会失败的模式被称为是 可反驳的(refutable)。一个这样的例子
便是 if let Some(x) = a_value 表达式中的 Some(x);如果变量 a_value 中的值是 None 而不是 Some,
那么 Some(x) 模式不能匹配。
函数参数、let 语句和 for 循环只能接受不可反驳的模式,因为通过不匹配的值程序无法进行有意义的工
作。if let 和 while let 表达式被限制为只能接受可反驳的模式,因为根据定义他们意在处理可能的失
败:条件表达式的功能就是根据成功或失败执行不同的操作。
通常我们无需担心可反驳和不可反驳模式的区别,不过确实需要熟悉可反驳性的概念,这样当在错误
信息中看到时就知道如何应对。遇到这些情况,根据代码行为的意图,需要修改模式或者使用模式的结构。
让我们看看一个尝试在 Rust 要求不可反驳模式的地方使用可反驳模式以及相反情况的例子。在示例
18-8 中,有一个 let 语句,不过模式被指定为可反驳模式 Some(x)。如你所见,这不能编译:

fn main() {

let some_option_value: Option = None;

let Some(x) = some_option_value;

}

示例 18-8: 尝试在 let 中使用可反驳模式
如果 some_option_value 的值是 None,其不会成功匹配模式 Some(x),表明这个模式是可反驳的。然
而, 因为 let 对于 None 匹配不能产生任何任何合法的代码,所以 let 语句只能接受不可反驳模式。Rust
会在编译时抱怨我们尝试在要求不可反驳模式的地方使用可反驳模式:
$ cargo run
Compiling patterns v0.1.0 (file:///projects/patterns)
error[E0005]: refutable pattern in local binding: None not covered
–> src/main.rs:3:9
|
3 | let Some(x) = some_option_value;
| ^^^^^^^ pattern None not covered
|
= note: let bindings require an “irrefutable pattern”, like a struct or an enum with only one variant
= note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
= note: the matched value is of type Option<i32>
help: you might want to use if let to ignore the variant that isn’t matched
|
3 | if let Some(x) = some_option_value { /* */ }
|
For more information about this error, try rustc --explain E0005.
error: could not compile patterns due to previous error
因为我们没有覆盖(也不可能覆盖!)到模式 Some(x) 的每一个可能的值, 所以 Rust 会合理地抗议。
为了修复在需要不可反驳模式的地方使用可反驳模式的情况,可以修改使用模式的代码:不同于使用
let,可以使用 if let。如此,如果模式不匹配,大括号中的代码将被忽略,其余代码保持有效。示例
18-9 展示了如何修复示例 18-8 中的代码。

fn main() {

let some_option_value: Option = None;

if let Some(x) = some_option_value {
println!(“{}”, x);
}

}

示例 18-9: 使用 if let 和一个带有可反驳模式的代码块来代替 let
我们给了代码一个得以继续的出路!虽然我们没办法在避免产生错误的情况下使用不可反驳模式,但这
段使用可反驳模式的代码是完全有效的。如果为 if let 提供了一个总是会匹配的模式,比如示例 18-10
中的 x,编译器会给出一个警告:

fn main() {

if let x = 5 {
println!(“{}”, x);
};

}

示例 18-10: 尝试把不可反驳模式用到 if let 上
Rust 会抱怨将不可反驳模式用于 if let 是没有意义的:
$ cargo run
Compiling patterns v0.1.0 (file:///projects/patterns)
warning: irrefutable if let pattern
–> src/main.rs:2:8
|
2 | if let x = 5 {
| ^^^^^^^^^
|
= note: #[warn(irrefutable_let_patterns)] on by default
= note: this pattern will always match, so the if let is useless
= help: consider replacing the if let with a let
warning: patterns (bin “patterns”) generated 1 warning
Finished dev [unoptimized + debuginfo] target(s) in 0.39s
Running target/debug/patterns
5
基于此,match匹配分支必须使用可反驳模式,除了最后一个分支需要使用能匹配任何剩余值的不可反
驳模式。Rust 允许我们在只有一个匹配分支的match中使用不可反驳模式,不过这么做不是特别有用,
并可以被更简单的 let 语句替代。
目前我们已经讨论了所有可以使用模式的地方, 以及可反驳模式与不可反驳模式的区别,下面让我们一
起去把可以用来创建模式的语法过目一遍吧。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值