From 8f317fa4dd2f29ffb1c210b771cebf85398b3462 Mon Sep 17 00:00:00 2001 From: Denis Nutiu Date: Tue, 5 Nov 2024 23:52:29 +0200 Subject: [PATCH] record progress: smart pointers --- exercises/19_smart_pointers/arc1.rs | 4 +-- exercises/19_smart_pointers/box1.rs | 6 ++-- exercises/19_smart_pointers/cow1.rs | 6 ++-- exercises/19_smart_pointers/rc1.rs | 12 +++---- solutions/19_smart_pointers/box1.rs | 49 +++++++++++++++++++++++++++-- 5 files changed, 60 insertions(+), 17 deletions(-) diff --git a/exercises/19_smart_pointers/arc1.rs b/exercises/19_smart_pointers/arc1.rs index 6bb860f..f44e4e1 100644 --- a/exercises/19_smart_pointers/arc1.rs +++ b/exercises/19_smart_pointers/arc1.rs @@ -23,13 +23,13 @@ fn main() { let numbers: Vec<_> = (0..100u32).collect(); // TODO: Define `shared_numbers` by using `Arc`. - // let shared_numbers = ???; + let shared_numbers = Arc::new(numbers); let mut join_handles = Vec::new(); for offset in 0..8 { // TODO: Define `child_numbers` using `shared_numbers`. - // let child_numbers = ???; + let child_numbers = shared_numbers.clone(); let handle = thread::spawn(move || { let sum: u32 = child_numbers.iter().filter(|&&n| n % 8 == offset).sum(); diff --git a/exercises/19_smart_pointers/box1.rs b/exercises/19_smart_pointers/box1.rs index d70e1c3..9dad835 100644 --- a/exercises/19_smart_pointers/box1.rs +++ b/exercises/19_smart_pointers/box1.rs @@ -12,18 +12,18 @@ // TODO: Use a `Box` in the enum definition to make the code compile. #[derive(PartialEq, Debug)] enum List { - Cons(i32, List), + Cons(i32, Box), Nil, } // TODO: Create an empty cons list. fn create_empty_list() -> List { - todo!() + List::Nil } // TODO: Create a non-empty cons list. fn create_non_empty_list() -> List { - todo!() + List::Cons(20, Box::new(List::Nil)) } fn main() { diff --git a/exercises/19_smart_pointers/cow1.rs b/exercises/19_smart_pointers/cow1.rs index 1566500..0c9c1d6 100644 --- a/exercises/19_smart_pointers/cow1.rs +++ b/exercises/19_smart_pointers/cow1.rs @@ -39,7 +39,7 @@ mod tests { let mut input = Cow::from(&vec); abs_all(&mut input); // TODO: Replace `todo!()` with `Cow::Owned(_)` or `Cow::Borrowed(_)`. - assert!(matches!(input, todo!())); + assert!(matches!(input, Cow::Borrowed(_))); } #[test] @@ -52,7 +52,7 @@ mod tests { let mut input = Cow::from(vec); abs_all(&mut input); // TODO: Replace `todo!()` with `Cow::Owned(_)` or `Cow::Borrowed(_)`. - assert!(matches!(input, todo!())); + assert!(matches!(input, Cow::Owned(_))); } #[test] @@ -64,6 +64,6 @@ mod tests { let mut input = Cow::from(vec); abs_all(&mut input); // TODO: Replace `todo!()` with `Cow::Owned(_)` or `Cow::Borrowed(_)`. - assert!(matches!(input, todo!())); + assert!(matches!(input, Cow::Owned(_))); } } diff --git a/exercises/19_smart_pointers/rc1.rs b/exercises/19_smart_pointers/rc1.rs index 48e19dc..f7c52dc 100644 --- a/exercises/19_smart_pointers/rc1.rs +++ b/exercises/19_smart_pointers/rc1.rs @@ -61,17 +61,17 @@ mod tests { jupiter.details(); // TODO - let saturn = Planet::Saturn(Rc::new(Sun)); + let saturn = Planet::Saturn(Rc::clone(&sun)); println!("reference count = {}", Rc::strong_count(&sun)); // 7 references saturn.details(); // TODO - let uranus = Planet::Uranus(Rc::new(Sun)); + let uranus = Planet::Uranus(Rc::clone(&sun)); println!("reference count = {}", Rc::strong_count(&sun)); // 8 references uranus.details(); // TODO - let neptune = Planet::Neptune(Rc::new(Sun)); + let neptune = Planet::Neptune(Rc::clone(&sun)); println!("reference count = {}", Rc::strong_count(&sun)); // 9 references neptune.details(); @@ -92,13 +92,13 @@ mod tests { drop(mars); println!("reference count = {}", Rc::strong_count(&sun)); // 4 references - // TODO + drop(venus); println!("reference count = {}", Rc::strong_count(&sun)); // 3 references - // TODO + drop(mercury); println!("reference count = {}", Rc::strong_count(&sun)); // 2 references - // TODO + drop(earth); println!("reference count = {}", Rc::strong_count(&sun)); // 1 reference assert_eq!(Rc::strong_count(&sun), 1); diff --git a/solutions/19_smart_pointers/box1.rs b/solutions/19_smart_pointers/box1.rs index dcf2377..189cc56 100644 --- a/solutions/19_smart_pointers/box1.rs +++ b/solutions/19_smart_pointers/box1.rs @@ -1,4 +1,47 @@ -fn main() { - // DON'T EDIT THIS SOLUTION FILE! - // It will be automatically filled after you finish the exercise. +// At compile time, Rust needs to know how much space a type takes up. This +// becomes problematic for recursive types, where a value can have as part of +// itself another value of the same type. To get around the issue, we can use a +// `Box` - a smart pointer used to store data on the heap, which also allows us +// to wrap a recursive type. +// +// The recursive type we're implementing in this exercise is the "cons list", a +// data structure frequently found in functional programming languages. Each +// item in a cons list contains two elements: The value of the current item and +// the next item. The last item is a value called `Nil`. + +#[derive(PartialEq, Debug)] +enum List { + Cons(i32, Box), + Nil, +} + +fn create_empty_list() -> List { + List::Nil +} + +fn create_non_empty_list() -> List { + List::Cons(42, Box::new(List::Nil)) +} + +fn main() { + println!("This is an empty cons list: {:?}", create_empty_list()); + println!( + "This is a non-empty cons list: {:?}", + create_non_empty_list(), + ); +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_create_empty_list() { + assert_eq!(create_empty_list(), List::Nil); + } + + #[test] + fn test_create_non_empty_list() { + assert_ne!(create_empty_list(), create_non_empty_list()); + } }