Rust

Rust 기본개념 - 패턴매칭 match

jobey 2024. 12. 9. 12:35
반응형

Match란?

Rust에서 패턴 매칭 분기를 위한 흐름제어 도구 입니다.

기본 문법

match 값 {
    패턴 => 표현식,
    패턴 => 표현식,
    // ...
}
  • : 매칭하려는 값입니다.
  • 패턴: 값과 비교할 패턴입니다.
  • 표현식: 패턴이 일치했을 때 실행할 코드입니다.

 

Match의 사용법

숫자 매칭

fn main() {
    let number = 3;

    match number {
        1 => println!("Number is one"),
        2 => println!("Number is two"),
        3 => println!("Number is three"),
        _ => println!("Number is something else"),
    }
}
  • 패턴: 1, 2, 3은 특정 숫자를 매칭합니다.
  • _(와일드카드): 위의 모든 패턴에 일치하지 않는 값을 처리합니다.

 

패턴의 종류

1. 리터럴 매칭

match x {
    42 => println!("The answer!"),
    _ => println!("Not the answer."),
}

 

2. 범위 매칭

match x {
    1..=5 => println!("Between 1 and 5 inclusive"),
    _ => println!("Outside the range"),
}

 

3. 구조체와 열거형 매칭

enum Weather {
    Sunny,
    Rainy,
    Snowy { cm: u32 },
}

fn describe_weather(weather: Weather) {
    match weather {
        Weather::Sunny => println!("It is sunny!"),
        Weather::Rainy => println!("It is rainy!"),
        Weather::Snowy { cm } => println!("It is snowy with {} cm of snow!", cm),
    }
}

 

4. 튜플 매칭

match (x, y) {
    (0, 0) => println!("Origin"),
    (x, 0) => println!("Point on the x-axis: x = {}", x),
    (0, y) => println!("Point on the y-axis: y = {}", y),
    _ => println!("Point somewhere else"),
}

 

5. 바인딩

match x {
    value @ 1..=5 => println!("Value in range: {}", value),
    _ => println!("Value out of range"),
}

 

안정성

Rust에서 macth는 가능한 모든 경우를 처리 해줘야 합니다. 컴파일러에서 가능한 모든 경우를 체크하고 처리가 되어있지 않다면 에러를 발생시킵니다. 그렇지 않으면 non-exhaustive patterns 에러가 발생합니다.

 

아래 예재를 보면 패턴 매칭이 커버할 수 있는 범위인 1,2를 넘어선 값이 x에 할당되어있습니다.

이런 경우 컴파일러에서 이를 잡아주지 않고 런타임까지 가게 된다면 프로그램에 문제가 발생하겠죠?

let x = 5;
match x {
    1 => println!("One"),
    2 => println!("Two"),
} // 컴파일 오류: 패턴이 불완전합니다.

 

그래서 아래와 같이 와일드 카드를 사용하여 그외 경우를 커버해줍니다.

match x {
    1 => println!("One"),
    2 => println!("Two"),
    _ => println!("Something else"),
}

 

Match의 심화 활용법

1. 값 반환

match는 표현식이므로 값을 반환할 수도 있습니다.

Rust에서는 명시적 return 키워드가 없으면 함수의 가장 마지막에 처리된 값을 반환합니다.

 

여기서는 match에서 반환한 값이 되겠네요

fn number_description(n: i32) -> &'static str {
    match n {
        0 => "zero",
        1 => "one",
        _ => "something else",
    }
}

 

2. 중첩된 매칭

enum Shape {
    Rectangle { width: u32, height: u32 },
    Circle { radius: u32 },
}

fn describe_shape(shape: Shape) {
    match shape {
        Shape::Rectangle { width, height } => {
            match (width, height) {
                (w, h) if w == h => println!("Square with side {}", w),
                _ => println!("Rectangle: {} x {}", width, height),
            }
        },
        Shape::Circle { radius } => println!("Circle with radius {}", radius),
    }
}

 

3. 가드사용

match x {
    n if n % 2 == 0 => println!("Even number: {}", n),
    _ => println!("Odd number"),
}

 

 

물론 match 없이 if문으로 이런 흐름을 처리하는게 더 나을 수도 있습니다. match 또한 중첩된경우 if문 만큼 가독성이 좋지 않기 때문에 상황에 따라 적절하게 선택하는게 좋을 것 같습니다.

반응형