1.4.0으로 업데이트

sarojaba authored
revision 23c2d8d6981ad12074927b36f3d4d0d0629f3bd7
match
# 5.143. 정합 (Match) - 99100%

종종, 둘 이상의 가능한 선택을 가지기 때문에, 단순한 [`if`][if]/`else`는 충분하지 않습니다. 또한, 조건들은 꽤 복잡할 수 있습니다. Rust는 복잡한 `if`/`else` 그룹을 대체하게 해주는 뭔가 더 강력한 `match`라는 키워드를 가지고 있습니다. 확인해볼까요?

```rust
let x = 5;

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

[if]: if.html

`match`는 표현식을 취한 뒤 값에 따라 분기합니다. 각 분기의 ‘팔(arm)’은 `val => expression` 형태를 가집니다. 값이 일치하면, 팔의 표현식이 평가될 것입니다. 이것은 `match`라 불리며 '패턴 매칭(pattern matching)'이라는 용어에서 비롯되었고, 이 `match`는 바로 'pattern matching'을 구현한 것입니다. There’s an [entire section on patterns][patterns] that covers all the patterns that are possible here패턴 매칭'을 구현한 것입니다. [패턴의 전체 섹션][patterns]은 가능한 패턴을 모두 다루고 있습니다.

[patterns]: patterns.html

그런데 어떤 큰 이점이 있나요? 음, 몇가지가 있습니다. 우선, `match`는 ‘철저한 확인(exhaustiveness checking)’을 강제합니다. 밑줄(`_`) 하나로 구성된 마지막 팔을 보았나요? 그 팔을 없애면, Rust는 에러를 표시할 것입니다.

```text
error: non-exhaustive patterns: `_` not covered
```

러스트는 우리에게 뭔가 값을 빠트렸음을 말하려 합니다. `x`는 정수이고, 러스트는 이것이 이미 나열된 값 이외의 어떤 다른 값이 될 수 있음을 알고 있으니까요. 예를 들어 `6`과 같은 값인 경우를 생각해 봅시다. 만약, `_`이 없다면, 그와 일치하는 팔도 없을 것이고, 따라서 러스트는 코드를 컴파일하려 하지 않을 겁니다. `_`는 마치 '다 잡는 팔(catch-all arm)' 처럼 행동합니다. 만약 다른 팔들과 일치하는 것이 없다면 `_`과 일치할 것이고, 이 '다 잡는 팔'이 있음으로 해서 `x`의 가능한 모든 값들에 대해서 각자 팔을 가진 것과 같게 되며, 따라서 우리의 프로그램은 성공적으로 컴파일될 것입니다.

`match`는 또한 수식입니다. 이것이 의미하는 바는, 이것을 `let` 바인딩의 오른쪽 부분에 놓거나 혹은 수식이 들어갈 곳에 직접적으로 사용할 수 있다는 것입니다.

```rust
let x = 5;

let number = match x {
1 => "one",
2 => "two",
3 => "three",
4 => "four",
5 => "five",
_ => "something else",
};
```

이것은 때때로 어떤 무언가를 다른 타입으로 변환하는데 있어 가장 좋은 방법이기도 합니다.

# 열거형들과의 일치

`match` 키워드의 또다른 중요한 사용 방법 중 하나는 열거형의 가능한 다양한 값들을 처리하는 것입니다.

```rust
enum Message {
Quit,
ChangeColor(i32, i32, i32),
Move { x: i32, y: i32 },
Write(String),
}

fn quit() { /* ... */ }
fn change_color(r: i32, g: i32, b: i32) { /* ... */ }
fn move_cursor(x: i32, y: i32) { /* ... */ }

fn process_message(msg: Message) {
match msg {
Message::Quit => quit(),
Message::ChangeColor(r, g, b) => change_color(r, g, b),
Message::Move { x: x, y: y } => move_cursor(x, y),
Message::Write(s) => println!("{}", s),
};
}
```

다시한번 말하지만, 러스트 컴파일러는 완벽성(exhaustiveness)을 검사하며, 따라서 이것은 당신에게 열거형의 모든 가능한 값들에 대해 그와 일치하는 팔을 만들기를 요구합니다. 만약 당신이 `_`를 사용하지 않은 상태에서 무언가 일치하지 않을 가능성을 남겨둔다면, 러스트는 컴파일할 때에 이것에 대한 에러 메시지를 출력할 것입니다.

이전의 `match` 사용방법과 달리, 보통의 `if`구문은 여기서 사용할 수 없습니다. 대신에 [`if let`][if-let]구문을 사용할 수 있는데, 이것은 마치 `match`구문의 단축된 형태로 보일 것입니다.

[if-let][if-let.html]