if let
어떤 사용 환경에서는 match
를 활용하는 게 애매한 경우가 있습니다. 예를 들어:
#![allow(unused)] fn main() { // Make `optional` of type `Option<i32>` let optional = Some(7); match optional { Some(i) => { println!("This is a really long string and `{:?}`", i); // ^ Needed 2 indentations just so we could destructure // `i` from the option. }, _ => {}, // ^ Required because `match` is exhaustive. Doesn't it seem // like wasted space? }; }
이런 경우 if let
을 사용하는 것이 더 간단하며, 추가로 실패했을 때의 처리도 가능합니다:
fn main() { // All have type `Option<i32>` let number = Some(7); let letter: Option<i32> = None; let emoticon: Option<i32> = None; // The `if let` construct reads: "if `let` destructures `number` into // `Some(i)`, evaluate the block (`{}`). if let Some(i) = number { println!("Matched {:?}!", i); } // If you need to specify a failure, use an else: if let Some(i) = letter { println!("Matched {:?}!", i); } else { // Destructure failed. Change to the failure case. println!("Didn't match a number. Let's go with a letter!"); } // Provide an altered failing condition. let i_like_letters = false; if let Some(i) = emoticon { println!("Matched {:?}!", i); // Destructure failed. Evaluate an `else if` condition to see if the // alternate failure branch should be taken: } else if i_like_letters { println!("Didn't match a number. Let's go with a letter!"); } else { // The condition evaluated false. This branch is the default: println!("I don't like letters. Let's go with an emoticon :)!"); } }
같은 방법으로 if let
을 다른 열거형에 활용할 수도 있습니다:
// Our example enum enum Foo { Bar, Baz, Qux(u32) } fn main() { // Create example variables let a = Foo::Bar; let b = Foo::Baz; let c = Foo::Qux(100); // Variable a matches Foo::Bar if let Foo::Bar = a { println!("a is foobar"); } // Variable b does not match Foo::Bar // So this will print nothing if let Foo::Bar = b { println!("b is foobar"); } // Variable c matches Foo::Qux which has a value // Similar to Some() in the previous example if let Foo::Qux(value) = c { println!("c is {}", value); } // Binding also works with `if let` if let Foo::Qux(value @ 100) = c { println!("c is one hundred"); } }
if let
의 또다른 장점은 파라미터화되지 않은 열거형 멤버도 매칭할 수 있다는 것입니다.
그 열거형이 PartialEq
를 구현하지도 포함하지도 않는 경우에도 가능하죠.
이런 경우 열거형 내부의 멤버에 접근할 수 없어 if Foo::Bar == a
는 실패하지만,
if let
은 여전히 동작한다는 것입니다.
도전을 즐기시나요? 다음 예제를 if let
을 이용해 고쳐봅시다:
// This enum purposely neither implements nor derives PartialEq. // That is why comparing Foo::Bar == a fails below. enum Foo {Bar} fn main() { let a = Foo::Bar; // Variable a matches Foo::Bar if Foo::Bar == a { // ^-- this causes a compile-time error. Use `if let` instead. println!("a is foobar"); } }