[Chapter 6-2] Rust match 흐름 제어 연산자

hwwwa·2021년 10월 28일
1

🦀 Rust

목록 보기
16/25

match 흐름 제어 연산자

러스트의 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를 이용하는 매칭

아래의 코드는 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을 다루지 않았음을 알려주며 버그가 발생할 것입니다.

_ 변경자(placeholder)

러스트는 모든 가능한 값을 나열하고싶지 않을 경우에 사용할 수 있는 특별 패턴인 _ 를 가지고 있습니다.

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가 강제했던 하나도 빠짐없는 검사를 잃게 됩니다. 어느 것을 사용할 것인지는 상황에 따른 적절한 사용자의 선택에 달린 문제입니다.

0개의 댓글