Rust на примерах — страница 16 из 65

Смотрите также:

Функции, enum и Option

if let

В некоторых случаях использование 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

while let

Так же, как иif let, while let может сделать неудобный match более терпимым. Рассмотрим следующий пример, в котором мы увеличиваем значение i:

#![allow(unused)]

fn main() {

// Создадим переменную `optional` с типом `Option`

let mut optional = Some(0);


// Неоднократно повторим наш тест.

loop {

match optional {

// Если `optional` деструктурируется, выполним следующий блок.

Some(i) => {

if i > 9 {

println!("Больше 9, уходим отсюда!");

optional = None;

} else {

println!("`i` равен `{:?}`. Попробуем еще раз.", i);

optional = Some(i + 1);