From 34aafa82f9b8266c6ea2a80f2cee03615a2c5297 Mon Sep 17 00:00:00 2001 From: Nidhal Messaoudi Date: Mon, 27 Feb 2023 21:36:51 +0100 Subject: [PATCH] Main exercises --- exercises/error_handling/errors5.rs | 2 +- exercises/iterators/iterators1.rs | 2 +- exercises/macros/macros4.rs | 1 + exercises/smart_pointers/arc1.rs | 2 +- exercises/smart_pointers/cow1.rs | 66 ++++++++++++++++++++--------- exercises/vecs/README.md | 2 + 6 files changed, 52 insertions(+), 23 deletions(-) diff --git a/exercises/error_handling/errors5.rs b/exercises/error_handling/errors5.rs index 6da06ef..eb5506c 100644 --- a/exercises/error_handling/errors5.rs +++ b/exercises/error_handling/errors5.rs @@ -4,7 +4,7 @@ // This exercise uses some concepts that we won't get to until later in the course, like `Box` and the // `From` trait. It's not important to understand them in detail right now, but you can read ahead if you like. -// For now, think of the `Box` type as an "I want anything that does ???" type, which, given +// For now, think of the `Box` type as an "I want anything that does ???" type, which, given // Rust's usual standards for runtime safety, should strike you as somewhat lenient! // In short, this particular use case for boxes is for when you want to own a value and you care only that it is a diff --git a/exercises/iterators/iterators1.rs b/exercises/iterators/iterators1.rs index 0379c6b..f9cc3b3 100644 --- a/exercises/iterators/iterators1.rs +++ b/exercises/iterators/iterators1.rs @@ -10,7 +10,7 @@ // I AM NOT DONE -fn main () { +fn main() { let my_fav_fruits = vec!["banana", "custard apple", "avocado", "peach", "raspberry"]; let mut my_iterable_fav_fruits = ???; // TODO: Step 1 diff --git a/exercises/macros/macros4.rs b/exercises/macros/macros4.rs index c1fc5e8..4ee9803 100644 --- a/exercises/macros/macros4.rs +++ b/exercises/macros/macros4.rs @@ -3,6 +3,7 @@ // I AM NOT DONE +#[rustfmt::skip] macro_rules! my_macro { () => { println!("Check out my macro!"); diff --git a/exercises/smart_pointers/arc1.rs b/exercises/smart_pointers/arc1.rs index 93a2703..ffb306a 100644 --- a/exercises/smart_pointers/arc1.rs +++ b/exercises/smart_pointers/arc1.rs @@ -32,7 +32,7 @@ fn main() { for offset in 0..8 { let child_numbers = // TODO joinhandles.push(thread::spawn(move || { - let sum: u32 = child_numbers.iter().filter(|n| *n % 8 == offset).sum(); + let sum: u32 = child_numbers.iter().filter(|&&n| n % 8 == offset).sum(); println!("Sum of offset {} is {}", offset, sum); })); } diff --git a/exercises/smart_pointers/cow1.rs b/exercises/smart_pointers/cow1.rs index 5fba251..885138a 100644 --- a/exercises/smart_pointers/cow1.rs +++ b/exercises/smart_pointers/cow1.rs @@ -4,6 +4,9 @@ // Cow is a clone-on-write smart pointer. // It can enclose and provide immutable access to borrowed data, and clone the data lazily when mutation or ownership is required. // The type is designed to work with general borrowed data via the Borrow trait. +// +// This exercise is meant to show you what to expect when passing data to Cow. +// Fix the unit tests by checking for Cow::Owned(_) and Cow::Borrowed(_) at the TODO markers. // I AM NOT DONE @@ -20,29 +23,52 @@ fn abs_all<'a, 'b>(input: &'a mut Cow<'b, [i32]>) -> &'a mut Cow<'b, [i32]> { input } -fn main() { - // No clone occurs because `input` doesn't need to be mutated. - let slice = [0, 1, 2]; - let mut input = Cow::from(&slice[..]); - match abs_all(&mut input) { - Cow::Borrowed(_) => println!("I borrowed the slice!"), - _ => panic!("expected borrowed value"), +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn reference_mutation() -> Result<(), &'static str> { + // Clone occurs because `input` needs to be mutated. + let slice = [-1, 0, 1]; + let mut input = Cow::from(&slice[..]); + match abs_all(&mut input) { + Cow::Owned(_) => Ok(()), + _ => Err("Expected owned value"), + } } - // Clone occurs because `input` needs to be mutated. - let slice = [-1, 0, 1]; - let mut input = Cow::from(&slice[..]); - match abs_all(&mut input) { - Cow::Owned(_) => println!("I modified the slice and now own it!"), - _ => panic!("expected owned value"), + #[test] + fn reference_no_mutation() -> Result<(), &'static str> { + // No clone occurs because `input` doesn't need to be mutated. + let slice = [0, 1, 2]; + let mut input = Cow::from(&slice[..]); + match abs_all(&mut input) { + // TODO + } } - // No clone occurs because `input` is already owned. - let slice = vec![-1, 0, 1]; - let mut input = Cow::from(slice); - match abs_all(&mut input) { - // TODO - Cow::Borrowed(_) => println!("I own this slice!"), - _ => panic!("expected borrowed value"), + #[test] + fn owned_no_mutation() -> Result<(), &'static str> { + // We can also pass `slice` without `&` so Cow owns it directly. + // In this case no mutation occurs and thus also no clone, + // but the result is still owned because it always was. + let slice = vec![0, 1, 2]; + let mut input = Cow::from(slice); + match abs_all(&mut input) { + // TODO + } + } + + #[test] + fn owned_mutation() -> Result<(), &'static str> { + // Of course this is also the case if a mutation does occur. + // In this case the call to `to_mut()` returns a reference to + // the same data as before. + let slice = vec![-1, 0, 1]; + let mut input = Cow::from(slice); + match abs_all(&mut input) { + // TODO + } } } diff --git a/exercises/vecs/README.md b/exercises/vecs/README.md index ebe90bf..8ff9b85 100644 --- a/exercises/vecs/README.md +++ b/exercises/vecs/README.md @@ -13,3 +13,5 @@ the other useful data structure, hash maps, later. ## Further information - [Storing Lists of Values with Vectors](https://doc.rust-lang.org/stable/book/ch08-01-vectors.html) +- [`iter_mut`](https://doc.rust-lang.org/std/primitive.slice.html#method.iter_mut) +- [`map`](https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.map)