Skip to content

Latest commit

 

History

History
213 lines (172 loc) · 3.54 KB

control-flow.md

File metadata and controls

213 lines (172 loc) · 3.54 KB

Control Flow

Control Flow primitives

  • if expressions
  • loop and while loops
  • match expressions
  • for loops
  • break and continue
  • return and ?

Using if as a statement

  • Tests if a boolean expression is true
  • Parentheses around the conditional are not necessary
  • Blocks need brackets, no shorthand
fn main() {
    if 1 == 2 {
        println!("integers are broken");
    } else if 'a' == 'b' {
        println!("characters are broken");
    } else {
        println!("that's what I thought");
    }
}

Using if as an expression

  • Every block is an expression
  • Note the final ; to terminate the let statement.
fn main() {
    let x = if 1 == 2 {
        100
    } else if 'a' == 'b' {
        200
    } else {
        300
    };
}

Using if as the final expression

Now the if expression is the result of the function:

fn some_function() -> i32 {
    if 1 == 2 {
        100
    } else if 'a' == 'b' {
        200
    } else {
        300
    }
}

Looping with loop

loop is used for (potentially) infinite loops

fn main() {
    let mut i = 0;
    loop {
        i += 1;
        if i > 100 { break; }
    }
}

Looping with loop

loop blocks are also expressions...

fn main() {
    let mut i = 0;
    let loop_result = loop {
        i += 1;
        if i > 10 { break 6; }
        println!("i = {}", i);
    };
    println!("loop_result = {}", loop_result);
}

while

  • while is used for conditional loops.
  • Loops while the boolean expression is true
fn main() {
    let mut i = 0;
    while i < 10 {
        i += 1;
        println!("i = {}", i);
    }
}

Control Flow with match

  • The match keyword does pattern matching
  • You can use it a bit like an if/else if/else expression
  • The first arm to match, wins
  • _ means match anything
    fn main() {
        let a = 4;
        match a % 3 {
            0 => { println!("divisible by 3") }
            _ => { println!("not divisible by 3") }
        }
    }

for loops

  • for is used for iteration
  • Here 0..10 creates a Range, which you can iterate
fn main() {
    for num in 0..10 {
        println!("{}", num);
    }
}

for loops

Lots of things are iterable

fn main() {
    for ch in "Hello".chars() {
        println!("{}", ch);
    }
}

for under the hood

  • What Rust actually does is more like...
  • (More on this in the section on Iterators)
fn main() {
    let mut iter = "Hello".chars().into_iter();
    loop {
        match iter.next() {
            Some(ch) => println!("{}", ch),
            None => break,
        }
    }
}

Break labels

If you have nested loops, you can label them to indicate which one you want to break out of.

fn main() {
    'cols: for x in 0..5 {
        'rows: for y in 0..5 {
            println!("x = {}, y = {}", x, y);
            if x + y >= 6 {
                break 'cols;
            }
        }
    }
}

Continue

Means go around the loop again, rather than break out of the loop

fn main() {
    'cols: for x in 0..5 {
        'rows: for y in 0..5 {
            println!("x = {}, y = {}", x, y);
            if x + y >= 4 {
                continue 'cols;
            }
        }
    }
}

return

  • return can be used for early returns
  • The result of the last expression of a function is always returned
fn get_number(x: bool) -> i32 {
    if x {
        return 42;
    }
    -1
}