添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
  1. Introduction
  2. Hello World
    1. Comments
    2. Formatted print
      1. Debug
      2. Display
        1. Testcase: List
      3. Formatting
  3. Primitives
    1. Literals and operators
    2. Tuples
    3. Arrays and Slices
  4. Custom Types
    1. Structures
    2. Enums
      1. use
      2. C-like
      3. Testcase: linked-list
    3. constants
  5. Variable Bindings
    1. Mutability
    2. Scope and Shadowing
    3. Declare first
    4. Freezing
  6. Types
    1. Casting
    2. Literals
    3. Inference
    4. Aliasing
  7. Conversion
    1. From and Into
    2. TryFrom and TryInto
    3. To and from Strings
  8. Expressions
  9. Flow of Control
    1. if/else
    2. loop
      1. Nesting and labels
      2. Returning from loops
    3. while
    4. for and range
    5. match
      1. Destructuring
        1. tuples
        2. arrays/slices
        3. enums
        4. pointers/ref
        5. structs
      2. Guards
      3. Binding
    6. if let
    7. let-else
    8. while let
  10. Functions
    1. Methods
    2. Closures
      1. Capturing
      2. As input parameters
      3. Type anonymity
      4. Input functions
      5. As output parameters
      6. Examples in std
        1. Iterator::any
        2. Searching through iterators
    3. Higher Order Functions
    4. Diverging functions
  11. Modules
    1. Visibility
    2. Struct visibility
    3. The use declaration
    4. super and self
    5. File hierarchy
  12. Crates
    1. Creating a Library
    2. Using a Library
  13. Cargo
    1. Dependencies
    2. Conventions
    3. Tests
    4. Build Scripts
  14. Attributes
    1. dead_code
    2. Crates
    3. cfg
      1. Custom
  15. Generics
    1. Functions
    2. Implementation
    3. Traits
    4. Bounds
      1. Testcase: empty bounds
    5. Multiple bounds
    6. Where clauses
    7. New Type Idiom
    8. Associated items
      1. The Problem
      2. Associated types
    9. Phantom type parameters
      1. Testcase: unit clarification
  16. Scoping rules
    1. RAII
    2. Ownership and moves
      1. Mutability
      2. Partial moves
    3. Borrowing
      1. Mutability
      2. Aliasing
      3. The ref pattern
    4. Lifetimes
      1. Explicit annotation
      2. Functions
      3. Methods
      4. Structs
      5. Traits
      6. Bounds
      7. Coercion
      8. Static
      9. Elision
  17. Traits
    1. Derive
    2. Returning Traits with dyn
    3. Operator Overloading
    4. Drop
    5. Iterators
    6. impl Trait
    7. Clone
    8. Supertraits
    9. Disambiguating overlapping traits
  18. macro_rules!
    1. Syntax
      1. Designators
      2. Overload
      3. Repeat
    2. DRY (Don't Repeat Yourself)
    3. DSL (Domain Specific Languages)
    4. Variadics
  19. Error handling
    1. panic
    2. abort & unwind
    3. Option & unwrap
      1. Unpacking options with ?
      2. Combinators: map
      3. Combinators: and_then
      4. Defaults: or, or_else, get_or_insert, get_or_insert_with
    4. Result
      1. map for Result
      2. aliases for Result
      3. Early returns
      4. Introducing ?
    5. Multiple error types
      1. Pulling Results out of Options
      2. Defining an error type
      3. Boxing errors
      4. Other uses of ?
      5. Wrapping errors
    6. Iterating over Results
  20. Std library types
    1. Box, stack and heap
    2. Vectors
    3. Strings
    4. Option
    5. Result
      1. ?
    6. panic!
    7. HashMap
      1. Alternate/custom key types
      2. HashSet
    8. Rc
    9. Arc
  21. Std misc
    1. Threads
      1. Testcase: map-reduce
    2. Channels
    3. Path
    4. File I/O
      1. open
      2. create
      3. read_lines
    5. Child processes
      1. Pipes
      2. Wait
    6. Filesystem Operations
    7. Program arguments
      1. Argument parsing
    8. Foreign Function Interface
  22. Testing
    1. Unit testing
    2. Documentation testing
    3. Integration testing
    4. Dev-dependencies
  23. Unsafe Operations
    1. Inline assembly
  24. Compatibility
    1. Raw identifiers
  25. Meta
    1. Documentation
    2. Playground

if let

For some use cases, when matching enums, match is awkward. For example:

#![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 is cleaner for this use case and in addition allows various failure options to be specified:

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 :)!");

In the same way, if let can be used to match any enum value:

// Our example enum
enum Foo {
    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");

Another benefit is that if let allows us to match non-parameterized enum variants. This is true even in cases where the enum doesn't implement or derive PartialEq. In such cases if Foo::Bar == a would fail to compile, because instances of the enum cannot be equated, however if let will continue to work.

Would you like a challenge? Fix the following example to use 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");

See also:

enum, Option, and the RFC