Rust의 Type시스템은 강력하다 - 너무 강력해서, 현업코드에서도 타입시스템을 믿고 Refactoring하는 경우가 많다.
가령 Enum
타입은, 내부 요소로 존재하는 모든 variants
들에 대해서, match
clause안에서 반드시 매치되길 강제한다. 아래 코드를 보자.
enum MySpecialEnumCollection {
Variant1,
Variant2,
Variant3,
Variant4,
}
fn main() {
let em = MySpecialEnumCollection::Variant1;
match em { // Error!
MySpecialEnumCollection::Variant1 => todo!(),
MySpecialEnumCollection::Variant2 => todo!(),
MySpecialEnumCollection::Variant3 => todo!(),
}
}
위의 코드는 아래와 같은 에러메세지를 띄운다.
missing match arm:
Variant4
not covered
이는, 추후 enum
의 특정 variant
가 추가되는 등의 요구사항이 있을 때 변경요구지점에 대한 모든 부분들을 컴파일러가 아주 손쉽게 찾아줄 수 있도록 하여, Refactoring을 아주 쉽게한다.
예제코드의 enum
명을 다시 보자 - MySpecialEnumCollection
.
태생이 귀찮음이 많은 개발자라면, 내부 요소들에 대해서, wildcard를 사용해보고 싶은 충동이 들 수 있겠다. 그리고 Rust는 그런 접근도 허용한다.
enum MySpecialEnumCollection {
Variant1,
Variant2,
Variant3,
Variant4,
}
fn main() {
let em = MySpecialEnumCollection::Variant1;
use MySpecialEnumCollection::*;
match em { //works!
Variant1 => todo!(),
Variant2 => todo!(),
Variant3 => todo!(),
Variant4 => todo!(),
}
}
그러나, 위와 같은 방법은 현업코드에서 절.대.로 추천하지 않는다. 그 이유는, 그러한 practice가 컴파일러를 통한 에러 표시 기능을 침묵시킬 수 있기 때문이다.
위의 코드에서 가령, Variant4
를 없애고, Varaint5
, Varaint6
을 추가했다고 생각해보자.
enum MySpecialEnumCollection {
Variant1,
Variant2,
Variant3,
// Variant4 removed
Variant5, // added
Variant6, // added
}
fn main() {
let em = MySpecialEnumCollection::Variant1;
use MySpecialEnumCollection::*;
match em { // !! still works!
Variant1 => todo!(),
Variant2 => todo!(),
Variant3 => todo!(),
Variant4 => todo!(),
}
}
위의 코드는 정상 작동한다. 그 이유는 Match
clause에서 Variant4
가 Variant1~3
을 제외한 다른 케이스에 대한 변수로 작동하여, 매칭 패턴을 만족시키기 때문이다.
따라서, Enum
에 대해 wildcard를 사용하는 패턴은 현업코드에서는 절.대.로 추천하지 않는다.
혹여, 너무 긴 Enum
이 문제라면 대신에 아래와 같이 alias
를 사용하도록 하자.
...
use MySpecialEnumCollection as EC;
match em {
EC::Variant1 => todo!(),
EC::Variant2 => todo!(),
EC::Variant3 => todo!(),
...