% Конструкция if let
Иногда хочется сделать определённые вещи менее неуклюже. Например,
скомбинировать if и let чтобы более удобно сделать сопоставление с образцом.
Для этого есть if let.
В качестве примера рассмотрим Option<T>. Если это Some<T>, мы хотим вызвать
функцию на этом значении, а если это None — не делать ничего. Вроде такого:
#![allow(unused)] fn main() { let option = Some(5); fn foo(x: i32) { } match option { Some(x) => { foo(x) }, None => {}, } }
Здесь необязательно использовать match. if тоже подойдёт:
#![allow(unused)] fn main() { let option = Some(5); fn foo(x: i32) { } if option.is_some() { let x = option.unwrap(); foo(x); } }
Но оба этих варианта выглядят странно. Мы можем исправить это с помощью if let:
#![allow(unused)] fn main() { let option = Some(5); fn foo(x: i32) { } if let Some(x) = option { foo(x); } }
Если сопоставление с образцом успешно, имена в образце связываются с соответствующими частями разбираемого значения, и блок исполняется. Если значение не соответствует образцу, ничего не происходит.
Если вы хотите делать что-то ещё при несовпадении с образцом, используйте
else:
#![allow(unused)] fn main() { let option = Some(5); fn foo(x: i32) { } fn bar() { } if let Some(x) = option { foo(x); } else { bar(); } }
while let
Похожим образом, while let можно использовать для перебора значений, пока
они соответствуют образцу. Код вроде такого:
#![allow(unused)] fn main() { let option: Option<i32> = None; loop { match option { Some(x) => println!("{}", x), _ => break, } } }
Превращается в такой:
#![allow(unused)] fn main() { let option: Option<i32> = None; while let Some(x) = option { println!("{}", x); } }