Exhaustive Switching — switch는 모든 경우를 빠짐없이 다뤄야 해요

Exhaustive Switching — switch는 모든 경우를 빠짐없이 다뤄야 해요

switch를 쓰다 보면 이런 경험 하신 적 있죠? 분명히 값이 몇 개일 줄 알았는데, 빠뜨린 경우가 하나 있어서 컴파일이 안 되는 순간요. Zig의 switch는 이걸 그냥 넘어가지 않아요. 철저하게, 모든 가능한 값을 다루라고 강제합니다.

출처: Zig Documentation

본문

switch 표현식에 else 절이 없다면, 반드시 그 타입이 가질 수 있는 모든 값을 빠짐없이 나열해야 해요. 하나라도 빠뜨리면 컴파일 오류가 납니다.

const Color = enum {
    auto,
    off,
    on,
};

test "exhaustive switching" {
    const color = Color.off;
    switch (color) {
        Color.auto => {},
        Color.on => {},
    }
}

이 코드를 실행해 보면 컴파일러가 이렇게 지적해 줍니다.

$ zig test test_unhandled_enumeration_value.zig
/home/ci/work/zig-bootstrap/zig/doc/langref/test_unhandled_enumeration_value.zig:9:5: error: switch must handle all possibilities
    switch (color) {
    ^~~~~~
/home/ci/work/zig-bootstrap/zig/doc/langref/test_unhandled_enumeration_value.zig:3:5: note: unhandled enumeration value: 'off'
    off,
    ^~~
/home/ci/work/zig-bootstrap/zig/doc/langref/test_unhandled_enumeration_value.zig:1:15: note: enum 'test_unhandled_enumeration_value.Color' declared here
const Color = enum {
              ^~~~

여기서 놓치기 쉬운 부분을 짚어볼게요. Color 열거형에는 auto, off, on 세 값이 있는데, switch (color)에는 autoon만 적혀 있죠. off가 빠져 있으니 컴파일러가 "unhandled enumeration value: 'off'"라고 정확히 어디를 빠뜨렸는지 알려줘요. 그러니 else 절을 쓰지 않는 이상, switch는 그 타입의 모든 경우를 다루는 게 의무라는 걸 기억하면 돼요. 이렇게 하면 나중에 열거형에 값을 하나 추가해서 이 switch를 갱신하는 걸 깜빡해도, 컴파일 시점에 바로 잡아주니까 안심할 수 있어요.

더 알아보기

  • switchelse 절을 쓰면 나머지 모든 값을 한 번에 처리할 수 있어요. 보통 열거형에 값을 추가할 일이 생길 때 else가 편할 수 있는데, 그 안전성과의 트레이드오프를 잘 저울질해 보세요.
  • 열거형 값뿐 아니라 다양한 패턴으로 switch를 쓰는 방법은 Switching with Enum Literals(다음 섹션)에서 계속 이어집니다.