Complete these tasks to reinforce what you learned in this module.
Define a recursive enum enum List { Cons(i32, Box<List>), Nil }. The
Box<List> on the recursive field is what makes this compile — without it the type would
have infinite size (see theory file 01). Build the list [1, 2, 3, 4, 5] using nested
Cons(..., Box::new(...)) ending in Nil. Then write recursive functions that pattern-match
on &List to (a) render the list as 1 -> 2 -> 3 -> 4 -> 5 -> Nil, (b) sum all the values,
and (c) count the elements. Print the rendering, the sum, and the length, each on its own
line, in the format shown. In C# you'd model this with a class Node { int Value; Node Next; }
where the Next field is implicitly a reference; in Rust you make that indirection explicit
with Box.
use List::{Cons, Nil};. Each recursive
function is a match over &List: the Cons(value, rest) arm does the work for value
then recurses on rest (which is a &Box<List> — deref coercion lets you pass it straight
to a &List parameter), and the Nil arm is the base case (0 for sum/length, "Nil" for
render). For rendering, format!("{} -> {}", value, render(rest)) chains nicely. Build the
list inside-out: the innermost piece is Box::new(Nil).// Task 1: a recursive cons list built with Box<T>. See tasks/TASKS.md.
//
// Define `enum List { Cons(i32, Box<List>), Nil }`, build the list [1, 2, 3, 4, 5],
// then print a rendering of it, its sum, and its length.
fn main() {
todo!("define a Box-based cons list, build [1,2,3,4,5], print render, sum, and length");
}
Create a shared, mutable integer as Rc::new(RefCell::new(0)) — Rc gives
multiple owners, RefCell lets you mutate through a shared (&) handle. Print
Rc::strong_count right after creating it. Make two more handles with Rc::clone, then print
the strong count again. Mutate the value through the first clone (+= 10) and the second
(+= 5) using borrow_mut(), and print the resulting value. Then drop the first clone and
print the strong count once more. Finally, print the value again through the remaining handle
to show it's unchanged and still shared. Match the output format exactly. This is the
single-threaded mirror of Arc<Mutex<T>>: in C#, two variables referencing the same object
that both mutate it is just the default — Rust makes the shared-ownership and
interior-mutability halves explicit.
use std::rc::Rc; and use std::cell::RefCell;. Prefer Rc::clone(&shared) over
shared.clone() — it signals "refcount bump, not deep copy." Rc::strong_count(&shared)
takes a reference and returns the current number of owners (it's 1 at creation, 3 after
two clones, 2 after one drop). Mutate with *a.borrow_mut() += 10; — the temporary
RefMut guard drops at the ;, so the borrows don't overlap. Read with shared.borrow()
(a Ref<i32> that Displays like the inner value). drop(a) decrements the count.// Task 2: shared mutable state with Rc<RefCell<T>> and Rc::strong_count.
// See tasks/TASKS.md.
//
// Create an Rc<RefCell<i32>>, clone it twice, mutate through the handles, and print the
// strong_count at each stage along with the value.
fn main() {
todo!("Rc<RefCell<i32>>: clone twice, mutate, print strong_count and value at each stage");
}