Rust cheatsheet examples part_1

lapp1stan

Stanislav Kniazev

Posted on February 15, 2024

Rust cheatsheet examples part_1

Basic Types & Variables

Boolean
  • bool - Boolean (true or false)
Unsigned integers
  • u8, u16, u32, u64, u128
Signed integers
  • i8, i16, i32, i64, i128
Floating point numbers
  • f32, f64
Platform specific integers
  • usize - Unsigned integer. Same number of bits as the platform's pointer type.
  • isize - Signed integer. Same number of bits as the platform's pointer type.
Characters and Strings
  • char - Unicode scalar value
  • &str - String slice
  • String - Owned string
Null / Nil

Rust doesn’t have the null feature that many other languages have. Null is a value that means there is no value there. Rust does have an enum that can encode the concept of a value being present or absent. This enum is Option<T>, and it is defined by the standard library as follows:

enum Option<T> {     
  Some(T), 
  None
}
Enter fullscreen mode Exit fullscreen mode

You can use Some and None directly without the Option:: prefix. The Option<T> enum is still just a regular enum, and Some(T) and None are still variants of type Option<T>.

Tuple
let coordinates = (82, 64);
let score = ("Team A", 12);
Enter fullscreen mode Exit fullscreen mode
Array & Slice

Slices are similar to arrays, but their length is not known at compile time. Instead, a slice is a two-word object; the first word is a pointer to the data, the second word is the length of the slice

let nums = [1, 2, 3, 4, 5];
let zeros = [0; 4]; // [0, 0, 0, 0]
let slice = &nums[1..4];

Enter fullscreen mode Exit fullscreen mode
Hashmap
use std::collections::HashMap;

let mut scores = HashMap::new();
scores.insert(String::from("Team1"), 900);
scores.entry("Team2".to_owned()).or_insert(250);
Enter fullscreen mode Exit fullscreen mode
Struct
struct Person {
    name: String,
    is_active: bool,
}

let person1 = Person {
    name: String::from("alex"),
    is_active: false,
};

struct Point(i32, i32, i32);
let white = Point(255, 255, 255);
Enter fullscreen mode Exit fullscreen mode
Enum
enum Action {
    Stop,
    Go { x: i32, y: i32 },
    Yell(String),
    ChangeColor(i32, i32, i32),
}

let act1 = Action::Stop;
let act2 = Action::Go { x: 10, y: 20 };
let act3 = Action::Yell("Hello".to_owned());
let act4 = Action::ChangeColor(255, 255, 0);
Enter fullscreen mode Exit fullscreen mode
Constant
const MAX_SCORE: u32 = 10000;
Enter fullscreen mode Exit fullscreen mode
Static variable
static APP_VERSION: u32 = 1;
static mut HIT_COUNT: u32 = 0;
Enter fullscreen mode Exit fullscreen mode
Mutability
let mut val = 5; 
val = 7;
Enter fullscreen mode Exit fullscreen mode
Shadowing
let val = 5; 
let val = val + 2;
Enter fullscreen mode Exit fullscreen mode
Type alias type Score = u64;

Control Flow

if and if-let

let maybe_num = Some(7);

if maybe_num.is_some() {
    println!("number is: {}", maybe_num.unwrap());
}

// `if let` allows various failure options to be specified:
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!");
}
Enter fullscreen mode Exit fullscreen mode

let-else

With let-else, a refutable pattern can match and bind variables in the surrounding scope like a normal let, or else diverge (e.g. breakreturnpanic!) when the pattern doesn't match.
The scope of name bindings is the main thing that makes this different from match or if let-else expressions.

let (Some(count_str), Some(item)) = (it.next(), it.next()) else { 
  panic!("Can't segment count item pair: '{s}'");
}; 

let Ok(count) = u64::from_str(count_str) else { 
    panic!("Can't parse integer: '{count_str}'"); 
};
Enter fullscreen mode Exit fullscreen mode

while-let

while let can make awkward match sequences more tolerable.

let mut optional = Some(0);

// This reads: "while `let` destructures `optional` into
// `Some(i)`, evaluate the block (`{}`). Else `break`.
while let Some(i) = optional {
    if i > 9 {
        println!("Greater than 9, quit!");
        optional = None;
    } else {
        println!("`i` is `{:?}`. Try again.", i);
        optional = Some(i + 1);
    } // Doesn't require explicitly handling the failing case.
}
Enter fullscreen mode Exit fullscreen mode

Loops

let mut counter = 0;
loop {
    counter += 1;
    if counter == 3 {
        break; // Exit loop
    }
}

let mut count = 0;
let result = loop {
    count += 1;
    if count == 5 {
        break count; // Return value from loop
    }
};

let mut num = 0;
while num < 50 {
    num += 1;
}
Enter fullscreen mode Exit fullscreen mode

Nested loops & labels

'outer: loop {
    'inner: loop {
        break; // This breaks the inner loop
        break 'outer; // This breaks the outer loop
    }
}
Enter fullscreen mode Exit fullscreen mode

for loop

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);
    }
}
Enter fullscreen mode Exit fullscreen mode

for loop takes ownership of v1_iter and makes it mutable behind the scenes.

let v1 = vec![1, 2, 3]; 
let v1_iter = v1.iter(); 

for val in v1_iter { 
  println!("Got: {}", val); 
}
Enter fullscreen mode Exit fullscreen mode

Pattern Matching ❤️

Rust provides powerful pattern matching capabilities through the match expression and if let syntax, which can destructure, test, and compare values in a clean and concise way.

let x = 3;
match x {  
    1 => println!("one"),  
    2 | 3 => println!("two or three"),  // multiple values
    4..=9 => println!("within range"), // matching ranges  
    x => println!("{}", x),  // matching named variables  
    _ => println!("default Case") // default case (ignores value)  
}

// Another example:
let option_value = Some(5); 

match option_value { 
  Some(value) => println!("The value is: {}", value), 
  None => println!("The value is missing"), 
} 
if let Some(value) = option_value { println!("The value is: {}", value); }

Enter fullscreen mode Exit fullscreen mode

Destructuring

match block can be used to destructure Tuples, Arrays/Slices, Enums, Pointers, Structs.

enum Color {
    Red,
    Blue,
    Green,
    RGB(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::CMYK(c, m, y, k) =>
            println!("Cyan: {}, magenta: {}, yellow: {}, key (black): {}!",
                c, m, y, k),
        ...
    }
}


Part 2 is coming soon.

let array = [1, -2, 6];

match array {
    // Binds the second and the third elements to the respective variables
    [0, second, third] =>
        println!("array[0] = 0, array[1] = {}, array[2] = {}", second, third),

    // Single values can be ignored with _
    [1, _, third] => println!(
        "array[0] = 1, array[2] = {} and array[1] was ignored",
        third
    ),
    ...
}
Enter fullscreen mode Exit fullscreen mode

More fun stuff - Destructuring examples

Binding

Indirectly accessing a variable makes it impossible to branch and use that variable without re-binding. match provides the @ sigil for binding values to names:

fn some_number() -> Option<u32> {
    Some(42)
}

fn main() {
    match some_number() {
        // Got `Some` variant, match if its value, bound to `n`,
        // is equal to 42.
        Some(n @ 42) => println!("The Answer: {}!", n),
        // Match any other number.
        Some(n)      => println!("Not interesting... {}", n),
        // Match anything else (`None` variant).
        _            => (),
    }
}
Enter fullscreen mode Exit fullscreen mode

Part 2 is coming soon!

💖 💪 🙅 🚩
lapp1stan
Stanislav Kniazev

Posted on February 15, 2024

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related

Rust cheatsheet examples part_2
rust Rust cheatsheet examples part_2

February 20, 2024

Rust cheatsheet examples part_1
rust Rust cheatsheet examples part_1

February 15, 2024