做这种情况分析的最简单的方法是,当你事先知道这些 case 的价值时,不介意把它们放在代码的中间.在本例中,您需要一个简单的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 link)
如果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"),
}
}
}
(playground link)
然而,如果你try 使用非常量变量,你会得到奇怪的输出.
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 link)
如果你运行这个程序,编译器会给你很多关于"不可访问模式"的警告,并且四次输出都是"输入等于a".问题在于,match语句中每行的左侧不只是一个表达式,而是一个pattern.
模式是一个类似于(x, [_, z], Some(_))
的表达式.它由基本变量(如x
和z
)、下划线(_
)、所有文字表达式(整数、浮点、元组、数组)和其他一些内容组成.
当Rust运行这样的匹配语句时,它会try 在语法上将输入与模式匹配.基本变量将匹配任何内容,并且该变量的值被设置为与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
,可以 for each 分支添加一个保护.守卫通过为分支添加额外的条件来匹配,从而稍微过滤分支.在本例中,我们匹配任何内容并将其绑定到变量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 link)
这比switch/case构造要详细一点,但我希望它清楚地说明了发生了什么.在每个分支上,变量x都被绑定到16,如果这等于变量A
(或B
或C
),则该分支被接受.否则,我们try 下一个分支.