#028 Feb 2023

28. Raw string

Curious to know how you can add a double quote in raw strings?

No escape sequences are recognized in raw strings, so adding a backslash does not work.

Use ### to mark the start and the end of a raw string.

1
2
3
4
5
6
7
8
println!("This is a double quote \" ");

// println!(r"This is a double quote " "); // Nope!
// println!(r"This is a double quote \" "); // Nope!

// And this works
println!(r#"This is a double quote " "#);
println!(r###"This is a double quote " "###);
#027 Jan 2023

27. Option's sum/product

Rust’s option implements Sum and Product traits too!

Use it when you want to get None if there is a None element and sum of values otherwise.

1
2
3
let nums: [Option<u32>;3] = [Some(1), Some(10), None];
let maybe_nums: Option<u32> = nums.into_iter().sum();
assert_eq!(maybe_nums, None);

or sum of the values …

1
2
3
let nums = [Some(1), Some(10), Some(100)];
let maybe_nums: Option<u32> = nums.into_iter().sum();
assert_eq!(maybe_nums, Some(111));

And product.

1
2
3
let nums = [Some(1), Some(10), Some(100)];
let maybe_nums: Option<u32> = nums.into_iter().product();
assert_eq!(maybe_nums, Some(1000));
#026 Jan 2023

26. Collecting into Option

Rust’s option implements FromIterator too!

Use it when you want to get None if there is a None element and values otherwise.

1
2
3
let cars = [Some("Porsche"), Some("Ferrari"), None];
let maybe_cars: Option<Vec<_>> = cars.into_iter().collect();
assert_eq!(maybe_cars, None);

or values …

1
2
3
let cars = [Some("Porsche"), Some("Ferrari"), Some("Skoda")];
let maybe_cars: Option<Vec<_>> = cars.into_iter().collect();
assert_eq!(maybe_cars, Some(vec!["Porsche", "Ferrari", "Skoda"]));
#025 Dec 2022

25. Option's iterator

Rust’s option implements an iterator!

1
2
3
4
let o: Option<u32> = Some(200u32);
let mut iter = o.into_iter();
let v = iter.next();
assert_eq!(v, Some(200u32));

Why is this useful? see example.

1
2
3
4
5
6
let include_this_pls = Some(300u32);
let r: Vec<u32> = (0..2).chain(include_this_pls).chain(2..5).collect();
assert_eq!(r, vec![0,1,300,2, 3,4]);
let but_not_this = None;
let r: Vec<u32> = (0..2).chain(but_not_this).chain(2..5).collect();
assert_eq!(r, vec![0,1,2,3,4]);
#024 Dec 2022

24. ..=X

As of 1.66, it is possible to use ..=X in patterns

1
2
3
4
5
6
let result = 20u32;

match result {
    0..=20 => println!("Included"),
    21.. => println!("Sorry"),
}
#023 Dec 2022

23. Enum's default value

Instead of manually implementing Default trait for an enum, you can derive it and explicitly tell which variant should be the default one.

1
2
3
4
5
6
7
8
9
#[derive(Default)]
enum Car{
    #[default]
    Porsche,
    Ferrari,
    Skoda
}

let car = Car::default();
#022 Nov 2022

22. Enum's Debug

Use Debug trait to print enum values if needed.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
#[derive(Default,Debug)]
enum Car{
    #[default]
    Porsche,
    Ferrari,
    Skoda
}

let car = Car::default();
println!("{:?}", car);
#021 Oct 2022

21. Zip longest

Sometimes there is a need to zip two iterables of various lengths.

If it is known which one is longer, then use the following approach:

First one must be longer.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
let nums1 = [1, 2, 3, 4];
let nums2 = [10, 20];

for (n1, n2) in nums1
    .into_iter()
    .zip(nums2.into_iter().chain(std::iter::repeat(0i32)))
{
    println!("{n1} - {n2}");
}
// Output:
// 1 - 10
// 2 - 20
// 3 - 0
// 4 - 0
#020 Sep 2022

20. let-else statements

As of 1.65, it is possible to use let statement with a refutable pattern.

1
2
3
4
5
6
7
let result: Result<i32, ()> = Ok(20);

let Ok(value) = result else {
  panic!("Heeeelp!!!");
};

assert_eq!(value, 20);
#019 Aug 2022

19. breaking from labeled blocks

As of 1.65, it is possible to label plain block expression and terminate that block early.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
let result = 'block: {
    let result = 20i32;
    if result < 10 {
        break 'block 1;
    }
    if result > 10 {
        break 'block 2;
    }
    3
};
assert_eq!(result, 2);