Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Выражения match

Syntax
MatchExpression
    match Scrutinee {
        InnerAttribute*
        MatchArms?
    }

ScrutineeExpressionexcept StructExpression

MatchArms
    ( MatchArm => ( ExpressionWithoutBlock , | ExpressionWithBlock ,? ) )*
    MatchArm => Expression ,?

MatchArmOuterAttribute* Pattern MatchArmGuard?

MatchArmGuardif Expression

Выражение match ветвится на основе образца. Точная форма сопоставления зависит от образца.

Выражение match имеет рассматриваемое выражение, которое является значением для сравнения с образцами.

Рассматриваемое выражение и образцы должны иметь одинаковый тип.

match ведет себя по-разному в зависимости от того, является ли рассматриваемое выражение выражением-местом или выражением-значением.

Если рассматриваемое выражение является выражением-значением, оно сначала вычисляется во временное местоположение, и полученное значение последовательно сравнивается с образцами в ветвях до тех пор, пока не будет найден совпадающий образец. Первая ветвь с совпадающим образцом выбирается в качестве цели ветвления match, любые переменные, привязанные образцом, присваиваются локальным переменным в блоке ветви, и управление переходит в блок.

Когда рассматриваемое выражение является выражением-местом, сопоставление не выделяет временное местоположение; однако привязка по значению может скопировать или переместить из области памяти. Когда это возможно, предпочтительнее сопоставлять по выражениям-местам, так как время жизни этих сопоставлений наследует время жизни выражения-места, а не ограничивается внутренней частью сопоставления.

Пример выражения match:

#![allow(unused)]
fn main() {
let x = 1;

match x {
    1 => println!("one"),
    2 => println!("two"),
    3 => println!("three"),
    4 => println!("four"),
    5 => println!("five"),
    _ => println!("something else"),
}
}

Переменные, привязанные внутри образца, ограничены областью видимости охраны сопоставления и выражения ветви.

Режим привязки (перемещение, копирование или ссылка) зависит от образца.

Несколько образцов сопоставления могут быть объединены с помощью оператора |. Каждый образец будет проверяться в последовательности слева направо до тех пор, пока не будет найден успешный совпадающий образец.

#![allow(unused)]
fn main() {
let x = 9;
let message = match x {
    0 | 1  => "not many",
    2 ..= 9 => "a few",
    _      => "lots"
};

assert_eq!(message, "a few");

// Демонстрация порядка сопоставления образцов.
struct S(i32, i32);

match S(1, 2) {
    S(z @ 1, _) | S(_, z @ 2) => assert_eq!(z, 1),
    _ => panic!(),
}
}

Note

2..=9 является Образцом диапазона, а не Выражением диапазона. Таким образом, в ветвях сопоставления могут использоваться только те типы диапазонов, которые поддерживаются образцами диапазонов.

Каждая привязка в каждом образце, разделенном |, должна присутствовать во всех образцах в ветви.

Каждая привязка с тем же именем должна иметь тот же тип и тот же режим привязки.

Охраны сопоставления

Ветви сопоставления могут принимать охраны сопоставления для дальнейшего уточнения критериев сопоставления случая.

Охраны образцов появляются после образца и состоят из выражения типа bool, следующего за ключевым словом if.

Когда образец успешно сопоставляется, выполняется выражение охраны. Если выражение вычисляется в true, образец успешно сопоставляется.

В противном случае проверяется следующий образец, включая другие сопоставления с оператором | в той же ветви.

#![allow(unused)]
fn main() {
let maybe_digit = Some(0);
fn process_digit(i: i32) { }
fn process_other(i: i32) { }
let message = match maybe_digit {
    Some(x) if x < 10 => process_digit(x),
    Some(x) => process_other(x),
    None => panic!(),
};
}

Note

Множественные сопоставления с использованием оператора | могут вызвать многократное выполнение охраны образца и его побочных эффектов. Например:

#![allow(unused)]
fn main() {
use std::cell::Cell;
let i : Cell<i32> = Cell::new(0);
match 1 {
    1 | _ if { i.set(i.get() + 1); false } => {}
    _ => {}
}
assert_eq!(i.get(), 2);
}

Охрана образца может ссылаться на переменные, привязанные в образце, за которым она следует.

Перед вычислением охраны берется разделяемая ссылка на часть рассматриваемого выражения, с которой сопоставляется переменная. Во время вычисления охраны эта разделяемая ссылка затем используется при доступе к переменной.

Только когда охрана вычисляется в true, значение перемещается или копируется из рассматриваемого выражения в переменную. Это позволяет использовать разделяемые заимствования внутри охраны без перемещения из рассматриваемого выражения в случае, если охрана не срабатывает.

Более того, удерживая разделяемую ссылку во время вычисления охраны, также предотвращается мутация внутри охраны.

Атрибуты на ветвях сопоставления

Внешние атрибуты разрешены на ветвях сопоставления. Единственные атрибуты, которые имеют смысл на ветвях сопоставления, это cfg и атрибуты проверки линтеров.

Внутренние атрибуты разрешены непосредственно после открывающей фигурной скобки выражения сопоставления в тех же контекстах выражений, что и атрибуты на выражениях-блоках.