Rust Tutorial Exercises, Part 2


Section 2: Borrowing (Immutably)

All of the "Borrowing (Immutably)" exercises involve manipulating the code at the following gist. (You may need to cut-and-paste from the gist link into the playpen, due to infrastructural and rate-limit issues.)

Core Exercises

Exercise 2.1

The distinction between a statement versus a true expression is sometimes confusing. In the code in [Borrowing Playpen], such confusion leads to the output:

    sum: got () expect 2450

rather than the correct:

    sum: got 2450 expect 2450

Identify and fix the bug.

Note: You will need to complete this exercise to do the others in this section.

Hint 1. If you are not sure what is "wrong" about the code, the fact that the lines marked with (***) found it necessary to use {:?} to format one supposed sum and {} to format another is a clue; look carefully at the generated output in those two places.

Hint 2. It may be useful to add type annotations to isolate where "the bad value" is being generated.

Hint 3. Ask your neighbor, or one of the helpers!

Exercise 2.2

Rename the fn main() in the [Borrowing Playpen] to fn any_name_but_main(), and hit the Run button again.

What changed?

Exercise 2.3a

Is it perhaps silly to write &vec1 on the line marked (**) in [Borrowing Playpen] ?

After all, let borrowed: &Vec<i32> = &vec1; already binds the result of that expression, right?

What will happen if you just replace the &vec1 below the (**) with borrowed, as in:

let also_a_sum = sum(borrowed);

Try it and see. What is the problem with this change alone?

Exercise 2.3b

Re-attempt to make the change to (**) in [Borrowing Playpen] to read:

let also_a_sum = sum(borrowed);

But this time, address the compiler's complaints in some manner by making further changes elsewhere.

Review Exercise

Exercise 2.4

Write a function, fn choose_vec, that takes two input Vec<i32> parameters (as moved arguments), and returns one of them, i.e. it has signature:

fn choose_vec(v1: Vec<i32>, v2: Vec<i32>) -> Vec<i32> { ... }

The function should choose whichever vector that has a larger element at index 0.

Include some unit tests for your choose_vec.

Extra Exercises

Exercise 2.5

Write a function, fn palindrome, that takes a borrowed &Vec<i32> and returns a boolean. It returns true if and only if the series of values in-order is equal to the reversed series. E.g. the series [2, 17, 4, 17, 2] is a palindrome, while [2, 17, 17] is not.

Exercise 2.6

It is not idiomatic in Rust to define a function that takes an immutably-borrowed &Vec<T> argument. Instead, one uses a borrowed slice &[T], which is more general.

We will be seeing more with slices in the future; for now, just try changing the signature of fn sum so that it takes a &[i32] instead of &Vec<i32>, and see if you can modify the resulting code to compile.

(Make sure you try to compile it first after making the change; the compiler often provides useful hints as to what needs changing.)


Section 3: Mutably Borrowing

All of the "Mutably Borrowing" exercises involve manipulating the code at the following playpen link:

Core Exercises

Exercise 3.1

Continuing the theme from a previous section: try lifting the let borrowed = &vec1; out of its expression block in Mutably Borrowing Playpen, so that the let borrowed binding is on the same level as the other statements in fn main.

What goes wrong?

Exercise 3.2

Can we simplify the code by replacing the four lines below (*) in Mutably Borrowing Playpen with the single:

let the_sum = sum(&vec1);

Why does this work? How does this differ from exercise 1?

Exercise 3.3

Write a function

fn zero_fill(v: &mut Vec<usize>, count: usize)

that pushes count zeroes onto the end of v.

Exercise 3.4

Is the usize annotation on the line labelled (***) in Mutably Borrowing Playpen necessary? Try removing it and see; the code should still compile.

So, what type is being assigned to i when the annotation is missing?

Can you do an experiment ot prove that i is not being assigned the type i32 when the annotation is missing?

What types do you think are being assigned to c and sum?

EXTRA EXERCISES

HINT: You may need to use methods we have not yet seen to do these exercises; the Vec API is visible at:

https://doc.rust-lang.org/stable/std/vec/struct.Vec.html

Exercise 3.5

Write a function that takes a &mut Vec<i32> and imperatively replaces its contents with its prefix-sum:

[v1, v2, v3, ...] is replaced with [v1, v1+v2, v1+v2+v3, ...].

Examples:

Exercise 3.6

Write a function that takes a &mut Vec<u32> and imperatively removes all of its zero entries, effectively filtering it so that it contains only positive values.

Examples: