如果您事先知道案例的值,并且不介意将它们放在代码中间,则执行此类案例分析的最简单方法是使用简单的match
表达式。
fn main() {
for &input in &[16, 23, 42, 43] {
match input {
23 => println!("Input is equal to a"),
16 => println!("Input is equal to b"),
43 => println!("Input is equal to c"),
_ => println!("Input does not equal any value"),
}
}
}
(Playground链接)
如果您的a
,b
和c
是编译时常量(即已知值或使用const
函数生成的值),则仍然可以直接进行匹配。
const A: i32 = 23;
const B: i32 = 16;
const C: i32 = generate_c();
const fn generate_c() -> i32 {
A + B + 4
}
fn main() {
for &input in &[16, 23, 42, 43] {
match input {
A => println!("Input is equal to a"),
B => println!("Input is equal to b"),
C => println!("Input is equal to c"),
_ => println!("Input does not equal any value"),
}
}
}
(示例链接)
然而,如果您尝试对非常量变量进行此操作,则会得到奇怪的输出。
fn generate_c(a: i32, b: i32) -> i32 {
a + b + 4
}
fn main() {
let a = 23;
let b = 16;
let c = generate_c(a, b);
for &input in &[16, 23, 42, 43] {
match input {
a => println!("Input is equal to a"),
b => println!("Input is equal to b"),
c => println!("Input is equal to c"),
_ => println!("Input does not equal any value"),
}
}
}
(playground链接)
如果您运行这个程序,编译器将会给您很多"不可到达的模式"的警告,并且输出结果将会是四次"输入等于a"。问题在于,match语句中每行左侧并不是简单的表达式,而是一个模式。
模式是如(x, [_, z], Some(_))
这样的一种表达式。它由基础变量(比如x
和z
)、下划线符号(_
)、所有字面表达式(整数、浮点数、元组、数组)以及其他几种内容构成。
当Rust运行match语句时,它会尝试将输入与模式进行句法匹配。基础变量可以匹配任何东西,该变量的值会被设置为该分支的作用域内所匹配到的内容。下划线符号(就像上面所有示例中使用的那样)也可以匹配任何东西,但它们并不绑定任何变量。
使用上述的const
版本时,常量A
、B
和C
会在代码中的各处替换为它们各自的字面值,所以输入会与这些字面值进行匹配。
使用变量版本时,在我们匹配a
、b
和c
时,这些字母被解释为基础变量,可以匹配任何东西。模式中不考虑变量的实际值。在代码中
let a = 14;
let b = 15;
let c = 16;
let input = 16;
match input {
a => println!("Input is equal to a"),
b => println!("Input is equal to b"),
c => println!("Input is equal to c"),
_ => println!("Input does not equal any value"),
}
第一个分支将总是匹配,并为其作用域中的输入赋予名称a
。
如果您需要匹配变量a
,b
和c
,则可以向每个分支添加一个保护条件。保护条件通过为分支添加附加条件来对分支进行进一步过滤以实现匹配。在本例中,我们匹配任何内容并将其绑定到变量x
,但接着检查x
是否等于a
(以及b
和c
)。
fn generate_c(a: i32, b: i32) -> i32 {
a + b + 4
}
fn main() {
let a = 23;
let b = 16;
let c = generate_c(a, b);
for &input in &[16, 23, 42, 43] {
match input {
x if x == a => println!("Input is equal to a"),
x if x == b => println!("Input is equal to b"),
x if x == c => println!("Input is equal to c"),
_ => println!("Input does not equal any value"),
}
}
}
(playground链接)
这种写法比switch / case结构稍微冗长一些,但我希望你能清楚地理解正在发生的事情。在每个分支中,变量x被绑定到16,然后如果它等于变量A
(或B
或C
),则执行该分支。否则,我们尝试下一个分支。
a
、b
和c
是常数还是在运行时生成的? - SCappella