Самый простой способ сделать такой анализ кейсов - это когда вы заранее знаете значения кейсов и не против их размещения в середине кода.В этом случае вам нужно простое 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"),
}
}
}
(ссылка на игровую площадку)
Если ваши 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"),
}
}
}
(ссылка на игровую площадку)
Еслиесли вы запустите это, компилятор выдаст вам много предупреждений о «недостижимых шаблонах», и на выходе все четыре раза будет «Input is равный a».Проблема в том, что левая сторона каждой строки в операторе сопоставления является не просто выражением, а шаблоном .
. Шаблон представляет собой выражение, подобное (x, [_, z], Some(_))
.Он состоит из базовых переменных (например, x
и z
), символов подчеркивания (_
), всех литеральных выражений (целых чисел, чисел с плавающей точкой, кортежей, массивов) и нескольких других вещей.
Когда Rust выполняет такой оператор сопоставления, он пытается синтаксически сопоставить входные данные с шаблоном.Базовые переменные будут совпадать с чем угодно, и значение этой переменной будет установлено равным тому, что соответствует области видимости этой ветви оператора сравнения.Символы подчеркивания (используемые во всех приведенных выше примерах) тоже совпадают, но не связывают никакие переменные.
В вышеприведенной версии 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"),
}
}
}
(ссылка на игровую площадку)
Это немного более многословно, чем конструкция переключателя / корпуса, но я надеюсь, что понятно, что происходит.В каждой ветви переменная x связана с 16, тогда, если она равна переменной A
(или B
или C
), то эта ветвь берется.В противном случае мы пробуем следующую ветку.