To choice

The if conditional selection is an expression (which can be used to assign), and all branches must return the same type. The condition need not be enclosed in parentheses; the code block followed by the condition must be enclosed in braces.

Example 1: if expression

fn main() {
    let number = 3;

    ifnumber ! =0 {
        println!("number was something other than zero"); }}Copy the code

Example 2: if-else expression

fn main() {
    let number = 3;

    if number < 5 {
        println!("condition was true");
    } else {
        println!("condition was false"); }}Copy the code

Example 3: if-else-if expression

fn main() {
    let n = 5;

    if n < 0 {
        println!("{} is negative", n);
    } else if n > 0 {
        println!("{} is positive", n);
    } else {
        println!("{} is zero", n); }}Copy the code

Looping statements

Rust provides three types of loops: loop, while, and for.

The loop cycle

Infinite loop, usually used with the break expression.

Example:

fn main() {
    // This is an infinite loop
    loop {
        println!("again!");
    }

    let mut counter = 0;

    let result = loop {
        counter += 1;
        // Sets the loop termination condition and returns a result
        if counter == 10 {
            break counter * 2; }};println!("The result is {}", result);
}
Copy the code

The while loop

Example:

fn main() {
    let mut number = 3;

    whilenumber ! =0 {
        println!("{}!", number); , number = number -1;
    }

    println!("LIFTOFF!!!");
}
Copy the code

The for loop

Example:

fn main() {
    // the value of 'n' is: 1, 2... 1, 100 (`.. 101 'is equivalent to' 1.. = 100 `)
    for n in 1.101 {
        if n % 15= =0 {
            println!("fizzbuzz");
        } else if n % 3= =0 {
            println!("fizz");
        } else if n % 5= =0 {
            println!("buzz");
        } else {
            println!("{}", n); }}let a = [10.20.30.40.50];
    // Use the for loop to iterate over the elements in the collection
    for element in a.iter() {
        println!("the value is: {}", element); }}Copy the code

Pattern matching

Rust provides pattern-matching functionality through the match keyword, similar to switch in C but more powerful.

A match expression consists of a match keyword, a value for matching, and one or more branches, each of which contains a pattern and an expression to be executed.

match VALUE {
    PATTERN1 => EXPRESSION1,
    PATTERN2 => EXPRESSION2,
    PATTERN3 => EXPRESSION3,
    ...
    PATTERNn => EXPRESSIONn,
}
Copy the code

PATTERN1, PATTERN2… If a match is successful, the expression after => in the branch is executed, and the subsequent branches are not matched. Where PATTERNn can be literals, tuples, enumerations, structures, wildcards, functions, and so on.

Requirements for pattern matching:

  • All branches must exhaust all possibilities.
  • Each branch must be an expression, and in general the return value type of these expressions must be the same.

Example:

enum Direction {
    East,
    West,
    North,
    South,
}
fn main() {
    let d_west = Direction::West;
    let d_str = match d_west {
        Direction::East => "East",
        Direction::North | Direction::South => {
            panic!("South or North");
        }, // This branch must trigger panic, and the return value type can be different from other branches_ = >"West"};println!("{}", d_str);
}
Copy the code

deconstruction

When the pattern to be matched is a compound type, you can extract some data from the value of the compound type.

Example 1: Deconstructing tuples

fn main() {
    let triple = (0, -2.3);

    println!("Tell me about {:? }", triple);

    match triple {
        // Deconstruct elements 2 and 3 in the tuple
        (0, y, z) => println!("First is `0`, `y` is {:? }, and `z` is {:? }", y, z),
        / / use `.. 'Ignore the other elements and match only the first element
        (1, ..)  => println!("First is `1` and the rest doesn't matter"),
        // '_' matches all values. It is usually placed last to match all possible remaining values_ = >println!("It doesn't matter what they are"),}}Copy the code

Example 2: Deconstructing enumerations

#[allow(dead_code)]
enum Color {
    Red,
    Blue,
    Green,
    RGB(u32.u32.u32),
    HSV(u32.u32.u32),
    HSL(u32.u32.u32),
    CMY(u32.u32.u32),
    CMYK(u32.u32.u32.u32),}fn main() {
    let color = Color::RGB(122.17.40);

    println!("What color is it?");

    match color {
        Color::Red   => println!("The color is Red!"),
        Color::Blue  => println!("The color is Blue!"),
        Color::Green => println!("The color is Green!"),
        Color::RGB(r, g, b) =>
            println!("Red: {}, green: {}, and blue: {}!", r, g, b),
        Color::HSV(h, s, v) =>
            println!("Hue: {}, saturation: {}, value: {}!", h, s, v),
        Color::HSL(h, s, l) =>
            println!("Hue: {}, saturation: {}, lightness: {}!", h, s, l),
        Color::CMY(c, m, y) =>
            println!("Cyan: {}, magenta: {}, yellow: {}!", c, m, y),
        Color::CMYK(c, m, y, k) =>
            println!("Cyan: {}, magenta: {}, yellow: {}, key (black): {}!", c, m, y, k),
    }
}
Copy the code

Example 3: Deconstructing structures

fn main() {
    struct Foo {
        x: (u32.u32),
        y: u32,}let foo = Foo { x: (1.2), y: 3 };

    match foo {
        Foo { x: (1, b), y } => println!("First of x is 1, b = {}, y = {} ", b, y),

        // You can rename the field
        Foo { y: 2, x: i } => println!("y is 2, i = {:? }", i),
        // Foo { y: 2, x } => println! ("y is 2, i = {:? }", x),

        // Can use '.. 'Ignore some fields.Foo { y, .. } = >println!("y = {}, we don't care about x", y),
    }
}
Copy the code

Example 4: Matching range

fn main() {
    let x = 1;
    match x {
        1 ..=10= >println!("One to ten"), _ = >println!("Other"),}let c = 'w';
    match c {
        'a' ..='z'= >println!("Lowercase"),
        'A' ..='Z'= >println!("Capital letters"), _ = >println!("Other Characters"),}}Copy the code

Example 5: Multiple matching

fn main() {
    let x = 1;
    / / match multiple mode, use ` | ` space
    match x {
        1 | 2= >println!("One or two"), _ = >println!("Other"),}}Copy the code

postconditions

An if expression can be placed after the match pattern, called the Match Guard.

Example:

fn main() {
    let x = 4;
    let y = false;
    match x {
        4 | 5 if y => println!("yes"), _ = >println!("no"),}}Copy the code

The binding

You can use the @ symbol to bind matching values in a pattern to a name, as described in Identifier Patterns.

Example:

fn age() - >u32 {
    15
}

fn main() {
    println!("Tell me what type of person you are");

    match age() {
        0= >println!("I haven't celebrated my first birthday yet"),
        n @ 1  ..= 12= >println!("I'm a child of age {:? }", n),
        n @ 13 ..= 19= >println!("I'm a teen of age {:? }", n),
        // Nothing bound. Return the result.
        n             => println!("I'm an old person of age {:? }", n),
    }
}
Copy the code

if let

In some cases, pattern matching can be simplified using an if let.

Example:

fn main() {
    let number = Some(7);
    let letter: Option<i32> = None;

    match number {
        Some(i) => {
            println!("Matched {:? }!", i); } _ = > {}// This branch does nothing, but cannot be omitted because pattern matching enumerates all possibilities
    };

    // We can match the above pattern to the following form
    if let Some(i) = number {
        println!("Matched {:? }!", i);
    }

    // You can also add an 'else' branch if you need to handle a mismatch
    if let Some(i) = letter {
        println!("Matched {:? }!", i);
    } else {
        println!("Didn't match a number. Let's go with a letter!"); }}Copy the code

while let

Like the if let, the while let simplifies pattern matching by focusing only on the values to be matched, leaving the rest of the values unprocessed explicitly.

Example:

fn main() {
    let mut optional = Some(0);

    loop {
        match optional {
            Some(i) => {
                if i > 9 {
                    println!("Greater than 9, quit!");
                    optional = None;
                } else {
                    println!("`i` is `{:? }`. Try again.", i);
                    optional = Some(i + 1); }} _ => {break; }}}// The pattern match in the loop above can be changed to the following form
    while let Some(i) = optional {
        if i > 9 {
            println!("Greater than 9, quit!");
            optional = None; // This is the end of loop condition
        } else {
            println!("`i` is `{:? }`. Try again.", i);
            optional = Some(i + 1); }}}Copy the code

The relevant data

The Rust Programming Language

The Rust Reference

Rust by Example