Rust conditionals: Difference between revisions

From wikinotes
Line 83: Line 83:
</syntaxhighlight>
</syntaxhighlight>
</blockquote><!-- Matching Option -->
</blockquote><!-- Matching Option -->
== Matching Ranges ==
<blockquote>
<syntaxhighlight lang="rust">
match val {
    i32::MIN..0 => "less than zero",
    0..5 => "is zero to five",
    5..i32::MAX => "is over five",
}
</syntaxhighlight>
<syntaxhighlight lang="rust">
use std::cmp::Ordering;
// todo
</syntaxhighlight>
</blockquote><!-- Matching Ranges -->
</blockquote><!-- Pattern Matching -->
</blockquote><!-- Pattern Matching -->



Revision as of 19:06, 9 February 2023

if statement

if num < 5 {
    // ..
} else if {
    // ..
} else {
    // ..
}

assign if

let weather = if season == "fall" { "lovely" } else { "fine I guess" } // ternary operator

match

Basics

Like a switch statement,
where compiler ensures that all possible options in datatype's range are handled,
that ensures the output type is the same for all branches (panic!() also allowed).

Especially useful for enums.

In the following case, if _ was omitted
you'd need to ensure the full range of possible i32 numbers were supported!.

// if num is '1', returns 'a'
// if num is >2, returns 'c'
let result = match num {
    1 => "a",
    2 => "b",
    _ => "c",   // anything other than 1 or 2
}

You can match multiple values

let result = match num {
    1 | 3 | 5 => "one three or five",
    _ => "something else"
}

Matching Enums

When matching a parametrized enum, you can access the tuple/struct/value that is bound to it

enum Pet {
    Cat(String, u8),
    Dog{name: String, age: u8},
    Lizard(u8),
}

let pet = Pet::Lizard(5);
match pet {
    Pet::Cat(name, age) => { format!("cat, name={}, age={}", name, age) },
    Pet::Dog(dog)       => { format!("dog, name={dog.name}, age={dog.age}") },
    Pet::Lizard(age)    => { format!("lizard, age={}", age) }
}

Matching Option

Option is just an enum, generally if you don't have a specific behaviour for None,
you return a new None in that branch.
However this an opportunity to fail if it is an appropriate location for it.

match some_value {
    Some(x) => "you received a value!",
    None    => None,
}

Matching Ranges

match val {
    i32::MIN..0 => "less than zero",
    0..5 => "is zero to five",
    5..i32::MAX => "is over five",
}
use std::cmp::Ordering;

// todo

if let

if let is essentially a one-branch match,
only caring about the value if it is non-none.
if my_value is None, then it returns None and the block does not run.

it does not take advantage of exhaustiveness checks.

if let Some(x) = my_value {
    println!("The value {} was bound!!", x);
}