В некоторых случаях использование match выглядит неуклюже. Например:
#![allow(unused)]
fn main() {
// Создаём переменную `optional` типа `Option`
let optional = Some(7);
match optional {
Some(i) => {
println!("Это очень большая строка и `{:?}`", i);
// ^ Нужно 2 отступа только для того, чтобы извлечь `i`
},
_ => {},
// ^ Обязателен, так как `match` исчерпывающий. Не выглядит ли это
// как потерянное пространство?
};
}
if let намного компактнее и выразительнее для данного случая и, кроме того, позволяет рассмотреть различные варианты ошибок.
fn main() {
// Все переменные типа `Option`
let number = Some(7);
let letter: Option = None;
let emoticon: Option = None;
// Конструкция `if let` читает, как: "Если `let` деструктуризирует `number` в
// `Some(i)`, выполнить блок (`{}`).
if let Some(i) = number {
println!("Соответствует {:?}!", i);
}
// Если нужно указать, что делать, в случае ошибки, можно добавить else:
if let Some(i) = letter {
println!("Соответствует {:?}!", i);
} else {
// Ошибка деструктуризации. Переходим к обработке ошибки.
println!("Не соответствует числу. Давайте попробуем строку!");
}
// Добавляем ещё одну ситуацию несоответствия образцу.
let i_like_letters = false;
if let Some(i) = emoticon {
println!("Соответствует {:?}!", i);
// Оцените условие `else if`, чтобы увидеть,
// должна ли быть альтернативная ветка отказа:
} else if i_like_letters {
println!("Не соответствует числу. Давайте попробуем строку!");
} else {
// Рассматриваем ложное условие. Эта ветвь по умолчанию:
println!("Мне не нравится сравнивать строки. Давайте возьмём смайлик :)!");
}
}
הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Точно так же, if let может быть использован для сравнения любого значения перечисления:
// Наш пример перечисления
enum Foo {
Bar,
Baz,
Qux(u32)
}
fn main() {
// Создание переменных примера
let a = Foo::Bar;
let b = Foo::Baz;
let c = Foo::Qux(100);
// Переменная `a` соответствует `Foo::Bar`
if let Foo::Bar = a {
println!("a = Foo::Bar");
}
// Переменная `b` не соответствует `Foo::Bar`.
// Поэтому ничего не выведется на экран
if let Foo::Bar = b {
println!("b = Foo::Bar");
}
// Переменная `c` соответствует `Foo::Qux`, которая имеет значение
// аналогичное `Some()` как в предыдущем примере:
if let Foo::Qux(value) = c {
println!("c ={}", value);
}
// С `if let` также работает и привязка
if let Foo::Qux(value @ 100) = c {
println!("c = 100");
}
}
הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Другое преимущество if let в том, что он позволяет сопоставлять нам не параметризованные варианты перечисления. Это возможно даже если для перечисления не реализован и не выведен типаж PartialEq. В некоторых случаях, if Foo::Bar == a не скомпилируется, потому что экземпляры перечисления не могут быть равны. Однако, с if let всё будет работать.
Хотите вызов? Исправьте следующий пример с использованием if let :
// Для это перечисление намеренно не добавлен #[derive(PartialEq)],
// и мы не реализовывали для него PartialEq. Вот почему сравнение Foo::Bar == a терпит неудачу.
enum Foo {Bar}
fn main() {
let a = Foo::Bar;
// Переменная соответствует Foo::Bar
if Foo::Bar == a {
// ^-- это вызовет ошибку компиляции. Используйте `if let` вместо этого.
println!("a is foobar");
}
}
הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
enum, Option, и RFC