New: The "Begin Rust" book

See a typo? Have a suggestion? Edit this page on Github

Get new blog posts via email

Heads up This blog post series has been updated and published as an eBook by FP Complete. I'd recommend reading that version instead of these posts. If you're interested, please check out the Rust Crash Course eBook.

Below are the solutions to the exercises from the last Rust Crash Course lesson, "Lifetimes and slices."

This post is part of a series based on teaching Rust at FP Complete. If you're reading this post outside of the blog, you can find links to all posts in the series at the top of the introduction post. You can also subscribe to the RSS feed.

Exercise 1

If you try just throwing in the ref keyword like this:

match person.age {
    Some(ref age) => {
        println!("Age is {}", age);
        *age += 1;
    }
    None => println!("No age provided"),
}

You'll get an error message:

error[E0594]: cannot assign to immutable borrowed content `*age`
  --> src/main.rs:16:13
   |
14 |         Some(ref age) => {
   |              ------- help: use a mutable reference instead: `ref mut age`
15 |             println!("Age is {}", age);
16 |             *age += 1;
   |             ^^^^^^^^^ cannot borrow as mutable

Instead, you need to say ref mut age. And if you're like me and regularly type in mut ref age instead of ref mut age, don't worry, the compiler's got your back:

error: the order of `mut` and `ref` is incorrect
  --> src/main.rs:14:14
   |
14 |         Some(mut ref age) => {
   |              ^^^^^^^ help: try switching the order: `ref mut`

error: aborting due to previous error

Exercise 2

You need to provide mutable references for the two arguments to swap. Additionally, in order to get a mutable reference to res, res itself needs to be mutable.

fn next(&mut self) -> Option<T> {
    let mut res = None;
    std::mem::swap(&mut res, &mut self.next);
    res
}

Exercise 3

We need to have two different parameters, and ensure that ret and the return value have the same lifetime parameter:

fn message_and_return<'a, 'b>(msg: &'a String, ret: &'b String) -> &'b String {
    println!("Printing the message: {}", msg);
    ret
}

Exercise 4

Since the data is stored in the program executable itself, it lives for the entire program execution. Therefore, the lifetime is 'static:

fn main() {
    let bytearray1: &'static [u8; 22] = b"Hello World in binary!";
    let bytearray2: &'static [u8] = b"Hello World in binary!";
    println!("{:?}", bytearray1);
    println!("{:?}", bytearray2);
}

Exercise 5

This is a great use case for the iterator method count:

fn main() {
    for arg in std::env::args() {
        println!(
            "arg: {}, characters: {}, bytes: {}",
            arg,
            arg.chars().count(),
            arg.bytes().count(),
            );
    }
}

Rust at FP Complete | Introduction

Get new blog posts via email