러스트의 match
는 일련의 패턴에 대해 어떤 값을 비교한 뒤 어떤 패턴에 매치되었는지를 바탕으로 코드를 수행하도록 해줍니다. 패턴은 리터럴값, 변수명, 와일드카드 등으로 구성될 수 있습니다. match
의 힘은 패턴의 표현성으로부터 오며 컴파일러는 모든 가능한 경우가 다루어지는지를 검사합니다.
아래는 열거형과 열거형의 variant를 패턴으로서 사용하는 match
표현식 코드입니다.
enum Coin {
Penny,
Nickel,
Dime,
Quarter,
}
fn value_in_cents(coin: Coin) -> u32 {
match coin {
Coin::Penny => 1,
Coin::Nickel => 5,
Coin::Dime => 10,
Coin::Quarter => {
println!("Quarter");
25
},
}
}
match
키워드 뒤에 오는 coin
은 표현식입니다. 괄호 안에는 각 arm(갈래)들이 있습니다. 첫 번째 arm은 Coin::Penny
이라는 패턴을 가지고 그 후에 패턴과 실행되는 코드를 구분해주는 =>
연산자가 있습니다. 첫 번째 arm의 경우 코드는 값 1
입니다. 각 arm은 그 다음 arm과 쉼표로 구분됩니다.
아래는 Quarter
variant가 UsState
값 또한 들고 있는 Coin
열거형 코드입니다.
#[derive(Debug)] // So we can inspect the state in a minute
enum UsState {
Alabama,
Alaska,
// ... etc
}
enum Coin {
Penny,
Nickel,
Dime,
Quarter(UsState),
}
앞서 구현한 value_in_cents
함수를 수정하여 Quarter
에 해당하는 arm에서 UsState
값을 출력하도록 해봅시다.
fn value_in_cents(coin: Coin) -> u32 {
match coin {
Coin::Penny => 1,
Coin::Nickel => 5,
Coin::Dime => 10,
Coin::Quarter(state) => {
println!("State quarter from {:?}!", state);
25
},
}
}
match
표현식 내에 variant Coin::Quarter
의 값과 매치되는 패턴에 state
라는 이름의 변수를 추가합니다. Coin::Quarter
가 매치될 때 state
변수는 UsState
에 대한 값에 바인드될 것입니다.
아래의 코드는 Option<i32>
상에서 match
를 이용하는 함수입니다.
fn plus_one(x: Option<i32>) -> Option<i32> {
match x {
None => None,
Some(i) => Some(i + 1),
}
}
let five = Some(5);
let six = plus_one(five);
let none = plus_one(None);
만약 위 코드의 match
안에서 None
케이스를 다루지 않는다면 러스트는 None
을 다루지 않았음을 알려주며 버그가 발생할 것입니다.
러스트는 모든 가능한 값을 나열하고싶지 않을 경우에 사용할 수 있는 특별 패턴인 _
를 가지고 있습니다.
let some_u8_value = 0u8;
match some_u8_value {
1 => println!("one"),
3 => println!("three"),
5 => println!("five"),
7 => println!("seven"),
_ => (),
}
_
는 그 전에 명시하지 않은 모든 가능한 경우에 대해 매칭됩니다. 위 코드에서 ()
는 단지 단위 값이므로 _
케이스에서는 어떠한 일도 일어나지 않을 것입니다.
if let
을 사용한 간결한 흐름 제어if let
문법은 하나의 패턴만 매칭 시키고 나머지 경우는 무시하는 경우에 사용합니다.
let some_u8_value = Some(0u8);
match some_u8_value {
Some(3) => println!("three"),
_ => (),
}
if let
을 사용하면 위의 코드를 아래처럼 더 짧게 쓸 수 있습니다.
let some_u8_value = Some(0u8);
if let Some(3) = some_u8_value {
println!("three");
}
if let
은 =
로 구분된 패턴과 표현식을 입력받습니다. match
보다 간결하지만 match
가 강제했던 하나도 빠짐없는 검사를 잃게 됩니다. 어느 것을 사용할 것인지는 상황에 따른 적절한 사용자의 선택에 달린 문제입니다.