패턴 매칭은 Rust에서 매우 중요한 언어 메커니즘으로, 함수형 언어에서 유래했습니다. 이는 추가 조건(guard 표현식)을 사용하여 복잡한 값의 변형을 선언적으로, 간결하게, 안전하게 분석할 수 있게 해주며, 이는 로직에 대한 유연성과 제어를 제공합니다.
exhaustiveness checking(모든 경우를 포괄적으로 검토하는 체크)가 없으면 패턴 매칭의 일부 시나리오에서 오류가 발생할 수 있습니다. 또한, 브랜치 순서와 guard 표현식에 대한 이해 부족은 로직이나 성능에서 오류를 초래할 수 있습니다.
Rust에서는 컴파일러가 모든 enum 변형(또는 더 간단한 패턴 구조)이 처리되었는지 확인하거나 _ 브랜치가 있는지 확인합니다. 브랜치는 guard 표현식(if 패턴 뒤)으로 추가 제한을 받을 수 있으며, 조건이 만족할 때만 "발생"합니다. 나머지 변형은 캡처되지 않습니다. 브랜치 순서는 중요하며, 위에서 아래로 검토됩니다.
코드 예:
enum Message { Hello, Data(i32), Quit, } fn handle(msg: Message) -> &'static str { match msg { Data(n) if n > 10 => "Big Data", Data(_) => "Some Data", Hello => "Greet!", Quit => "Bye", } }
주요 특징:
패턴이 일치하지만 조건이 만족하지 않으면 guard가 있는 브랜치가 실행되나요?
아니오, 그런 경우 검사는 다음 적합한 브랜치로 넘어갑니다. 패턴 + guard는 원자적인 "필터"입니다; 두 가지 모두 일치해야만 브랜치의 본체가 실행됩니다.
match의 브랜치 순서가 성능에 영향을 미치나요?
네. 특히 guard가 있는 유사한 패턴이 많은 경우: 컴파일러는 브랜치를 위에서 아래로 검사하므로 런타임 검사 속도에 영향을 미칩니다 — 더 자주 발생하는 값을 먼저 처리하는 것이 좋습니다.
exhaustiveness checking 을 생략하고 '_' 브랜치만 두는 것이 가능한가요?
기술적으로 가능하지만, 신뢰성을 잃게 됩니다: 타입이 새로운 요소를 제외하거나 추가하면, 컴파일러는 처리되지 않은 경우에 대해 경고하지 않습니다. 중요한 경우를 항상 명시적으로 처리하고, "_"는 최후의 수단으로 사용하는 것이 좋습니다.
guard 표현식이 있는 enum의 match 코드에서, guard가 있는 패턴이 마지막에 위치하고 있지만 대부분의 값이 초기 브랜치인 '_'를 통해 직접 이동하며 필요한 처리가 절대 이루어지지 않는 경우.
장점:
단점:
먼저 가장 빈번하고 중요한 변형(guard 포함)을 나열한 후, 나머지를 exhaustively 처리합니다 — 불필요한 코드를 "_"에 넣지 않습니다.
장점:
단점: