Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

if let

어떤 경우에는 열거형을 매칭할 때 match가 어색할 수 있습니다. 예를 들어:

#![allow(unused)]
fn main() {
// `Option<i32>` 타입의 `optional` 생성
let optional = Some(7);

match optional {
    Some(i) => println!("이것은 정말 긴 문자열이며 `{:?}`입니다", i),
    _ => {},
    // ^ `match`는 철저해야(exhaustive) 하기 때문에 필요합니다. 공간 낭비처럼
// 보이진 않나요?
};

}

이런 경우 if let이 더 깔끔하며, 추가로 다양한 실패 옵션을 지정할 수 있습니다:

fn main() {
    // 모두 `Option<i32>` 타입입니다
    let number = Some(7);
    let letter: Option<i32> = None;
    let emoticon: Option<i32> = None;

    // `if let` 구문은 다음과 같이 읽힙니다: "만약 `let`이 `number`를
// `Some(i)`로 구조 분해한다면, 블록(`{}`)을 실행하라."
    if let Some(i) = number {
        println!("{:?}가 매칭되었습니다!", i);
    }

    // 실패한 경우를 지정해야 한다면, else를 사용하세요:
    if let Some(i) = letter {
        println!("{:?}가 매칭되었습니다!", i);
    } else {
        // 구조 분해에 실패했습니다. 실패 사례로 전환합니다.
        println!("숫자와 매칭되지 않았습니다. 문자로 해봅시다!");
    }

    // 변경된 실패 조건을 제공합니다.
    let i_like_letters = false;

    if let Some(i) = emoticon {
        println!("{:?}가 매칭되었습니다!", i);
    // 구조 분해에 실패했습니다. 다른 실패 분기를 타야 하는지
// `else if` 조건을 평가합니다:
    } else if i_like_letters {
        println!("숫자와 매칭되지 않았습니다. 문자로 해봅시다!");
    } else {
        // 조건이 거짓(false)으로 평가되었습니다. 이 분기가 기본입니다:
        println!("문자는 별로예요. 이모티콘 :)으로 가봅시다!");
    }
}

같은 방식으로, if let은 모든 열거형 값을 매칭하는 데 사용될 수 있습니다:

// 예제 열거형
enum Foo {
    Bar,
    Baz,
    Qux(u32)
}

fn main() {
    // 예제 변수 생성
    let a = Foo::Bar;
    let b = Foo::Baz;
    let c = Foo::Qux(100);

    // 변수 a는 Foo::Bar와 매칭됩니다
    if let Foo::Bar = a {
        println!("a는 foobar입니다");
    }

    // 변수 b는 Foo::Bar와 매칭되지 않습니다
// 따라서 아무것도 출력되지 않습니다
    if let Foo::Bar = b {
        println!("b는 foobar입니다");
    }

    // 변수 c는 값을 가진 Foo::Qux와 매칭됩니다
// 앞선 예제의 Some()과 유사합니다
    if let Foo::Qux(value) = c {
        println!("c는 {}입니다", value);
    }

    // 바인딩은 `if let`에서도 작동합니다
    if let Foo::Qux(value @ 100) = c {
        println!("c는 100입니다");
    }
}

또 다른 장점은 if let을 사용하면 파라미터가 없는 열거형 변체도 매칭할 수 있다는 점입니다. 이는 열거형이 PartialEq를 구현하거나 유도하지 않는 경우에도 마찬가지입니다. 이러한 경우 if Foo::Bar == a는 열거형 인스턴스를 비교할 수 없기 때문에 컴파일에 실패하지만, if let은 계속 작동합니다.

도전해 보시겠습니까? 다음 예제를 if let을 사용하도록 수정해 보세요:

// 이 열거형은 의도적으로 PartialEq를 구현하거나 유도(derive)하지 않았습니다.
// 그래서 아래에서 Foo::Bar == a 를 비교하는 것이 실패합니다.
enum Foo {Bar}

fn main() {
    let a = Foo::Bar;

    // 변수 a는 Foo::Bar와 매칭됩니다
    if Foo::Bar == a {
    // ^-- 이것은 컴파일 타임 에러를 발생시킵니다. 대신 `if let`을 사용하세요.
        println!("a는 foobar입니다");
    }
}

참고:

enum, Option, 그리고 RFC