Сопоставление шаблона с кортежем

#rust #pattern-matching

#Ржавчина #сопоставление шаблона

Вопрос:

Я пытаюсь сопоставить с кортежем, созданным из деконструированного варианта перечисления, подобного этому:

 enum Enum {
  Var {
    field1: Option<String>,
    field2: Option<String>
  }
}

let var = Enum::Var {
  field1: Some("aaa".to_string()),
  field2: None
}

match var {
  Enum::Var {field1, field2} => {
    match (field1, field2) {
      (Some("aaa".to_string()), None) => (),
      _ => panic!()
    }
  }
  _ => panic!()
}

  

Однако я получаю сообщение об ошибке

 error: expected one of `)`, `,`, `...`, `..=`, `..`, or `|`, found `.`
  --> src/parser/test_admonitions.rs:61:22
   |
61 |         (Some("aaa".to_string()), None) => {}
   |                      ^
   |                      |
   |                      expected one of `)`, `,`, `...`, `..=`, `..`, or `|`
   |                      help: missing `,`

error: aborting due to 1 previous error
  

Почему это? Почему я не могу сопоставить с кортежем?

Ответ №1:

Почему я не могу сопоставить с кортежем?

Вы можете сопоставить с кортежем.

Чего вы не можете сделать, так это сопоставить с произвольными выражениями, шаблоны — это ограниченный синтаксис.

Правильный способ проверить, соответствует ли первый элемент кортежа "aaa" (или, в более общем смысле, соответствует нетривиальному условию), — это использовать защиту шаблона:

 match (field1, field2) {
    (Some(a), None) if a == "aaa" => (),
    _ => panic!()
}
  

кроме того, в косвенном обращении через кортеж нет необходимости, шаблоны имеют «глубину», поэтому вы можете сделать то же самое непосредственно со структурой:

 match var {
    Enum::Var {field1: Some(a), field2: None} if a == "aaa" => {
    }
    _ => panic!()
}
  

Ответ №2:

В дополнение к защите соответствия, как показано на моем @Masklinn, вы можете использовать Option::as_deref() для преобразования Option<String> в Option<amp;str> и сопоставления с последним:

 match var {
    Enum::Var { field1, field2 } => match (field1.as_deref(), field2.as_deref()) {
        (Some("aaa"), None) => (),
        _ => panic!(),
    },
}