diff --git a/.all-contributorsrc b/.all-contributorsrc index 14ec3a98..ab5d1424 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -2136,6 +2136,60 @@ "contributions": [ "content" ] + }, + { + "login": "proofconstruction", + "name": "proofconstruction", + "avatar_url": "https://avatars.githubusercontent.com/u/74747193?v=4", + "profile": "https://github.com/proofconstruction", + "contributions": [ + "infra" + ] + }, + { + "login": "IVIURRAY", + "name": "IVIURRAY", + "avatar_url": "https://avatars.githubusercontent.com/u/16007179?v=4", + "profile": "https://www.youtube.com/channel/UCQCjA6qUutAtWqkCA4Z36CQ", + "contributions": [ + "content" + ] + }, + { + "login": "b-apperlo", + "name": "Bert Apperlo", + "avatar_url": "https://avatars.githubusercontent.com/u/91734527?v=4", + "profile": "https://github.com/b-apperlo", + "contributions": [ + "content" + ] + }, + { + "login": "FWDekker", + "name": "Florine W. Dekker", + "avatar_url": "https://avatars.githubusercontent.com/u/13442533?v=4", + "profile": "https://fwdekker.com/", + "contributions": [ + "content" + ] + }, + { + "login": "luhem7", + "name": "Mehul Gangavelli", + "avatar_url": "https://avatars.githubusercontent.com/u/4008215?v=4", + "profile": "https://github.com/luhem7", + "contributions": [ + "content" + ] + }, + { + "login": "Frosthage", + "name": "Mikael Frosthage", + "avatar_url": "https://avatars.githubusercontent.com/u/14823314?v=4", + "profile": "https://github.com/Frosthage", + "contributions": [ + "content" + ] } ], "contributorsPerLine": 8, @@ -2144,5 +2198,6 @@ "repoType": "github", "repoHost": "https://github.com", "skipCi": true, - "commitConvention": "angular" + "commitConvention": "angular", + "commitType": "docs" } diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index bf2a041a..1b244b1a 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -14,6 +14,8 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 + - name: Fetch & maybe update Cargo.lock + run: cargo fetch --locked - name: Build run: cargo build --verbose - name: Run tests diff --git a/AUTHORS.md b/AUTHORS.md index 50a477c0..723cc4a8 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -303,6 +303,12 @@ authors. b1ue64
b1ue64

🖋 lazywalker
lazywalker

🖋 + proofconstruction
proofconstruction

🚇 + IVIURRAY
IVIURRAY

🖋 + Bert Apperlo
Bert Apperlo

🖋 + Florine W. Dekker
Florine W. Dekker

🖋 + Mehul Gangavelli
Mehul Gangavelli

🖋 + Mikael Frosthage
Mikael Frosthage

🖋 diff --git a/exercises/enums/enums3.rs b/exercises/enums/enums3.rs index 69ba0728..5d284417 100644 --- a/exercises/enums/enums3.rs +++ b/exercises/enums/enums3.rs @@ -20,6 +20,7 @@ struct State { color: (u8, u8, u8), position: Point, quit: bool, + message: String } impl State { @@ -31,9 +32,7 @@ impl State { self.quit = true; } - fn echo(&self, s: String) { - println!("{}", s); - } + fn echo(&mut self, s: String) { self.message = s } fn move_position(&mut self, p: Point) { self.position = p; @@ -57,6 +56,7 @@ mod tests { quit: false, position: Point { x: 0, y: 0 }, color: (0, 0, 0), + message: "hello world".to_string(), }; state.process(Message::ChangeColor(255, 0, 255)); state.process(Message::Echo(String::from("hello world"))); @@ -67,5 +67,6 @@ mod tests { assert_eq!(state.position.x, 10); assert_eq!(state.position.y, 15); assert_eq!(state.quit, true); + assert_eq!(state.message, "hello world"); } } diff --git a/exercises/hashmaps/hashmaps2.rs b/exercises/hashmaps/hashmaps2.rs index f9138486..a5925690 100644 --- a/exercises/hashmaps/hashmaps2.rs +++ b/exercises/hashmaps/hashmaps2.rs @@ -81,4 +81,13 @@ mod tests { let count = basket.values().sum::(); assert!(count > 11); } + + #[test] + fn all_fruit_types_in_basket() { + let mut basket = get_fruit_basket(); + fruit_basket(&mut basket); + for amount in basket.values() { + assert_ne!(amount, &0); + } + } } diff --git a/exercises/hashmaps/hashmaps3.rs b/exercises/hashmaps/hashmaps3.rs index 4b48e093..08e977c3 100644 --- a/exercises/hashmaps/hashmaps3.rs +++ b/exercises/hashmaps/hashmaps3.rs @@ -18,9 +18,8 @@ use std::collections::HashMap; -// A structure to store team name and its goal details. +// A structure to store the goal details of a team. struct Team { - name: String, goals_scored: u8, goals_conceded: u8, } diff --git a/exercises/move_semantics/move_semantics2.rs b/exercises/move_semantics/move_semantics2.rs index 5821b52b..72d37fa4 100644 --- a/exercises/move_semantics/move_semantics2.rs +++ b/exercises/move_semantics/move_semantics2.rs @@ -1,8 +1,8 @@ // move_semantics2.rs // // Expected output: -// vec0 has length 3 content `[22, 44, 66]` -// vec1 has length 4 content `[22, 44, 66, 88]` +// vec0 has length 3, with contents `[22, 44, 66]` +// vec1 has length 4, with contents `[22, 44, 66, 88]` // // Execute `rustlings hint move_semantics2` or use the `hint` watch subcommand // for a hint. @@ -12,15 +12,13 @@ fn main() { let vec0 = Vec::new(); - // Do not move the following line! let mut vec1 = fill_vec(vec0); - // Do not change the following line! - println!("{} has length {} content `{:?}`", "vec0", vec0.len(), vec0); + println!("{} has length {}, with contents: `{:?}`", "vec0", vec0.len(), vec0); vec1.push(88); - println!("{} has length {} content `{:?}`", "vec1", vec1.len(), vec1); + println!("{} has length {}, with contents `{:?}`", "vec1", vec1.len(), vec1); } fn fill_vec(vec: Vec) -> Vec { diff --git a/info.toml b/info.toml index 2add5f0c..cacad134 100644 --- a/info.toml +++ b/info.toml @@ -260,8 +260,8 @@ name = "vecs2" path = "exercises/vecs/vecs2.rs" mode = "test" hint = """ -Hint 1: `i` is each element from the Vec as they are being iterated. Can you try -multiplying this? +Hint 1: `element` is each element from the Vec as they are being iterated. Can you +try multiplying this? Hint 2: For the first function, there's a way to directly access the numbers stored in the Vec, using the * dereference operator. You can both access and write to the @@ -287,23 +287,24 @@ Also: Try accessing `vec0` after having called `fill_vec()`. See what happens!"" [[exercises]] name = "move_semantics2" path = "exercises/move_semantics/move_semantics2.rs" -mode = "compile" +mode = "test" hint = """ -So, `vec0` is passed into the `fill_vec` function as an argument. In Rust, -when an argument is passed to a function and it's not explicitly returned, -you can't use the original variable anymore. We call this "moving" a variable. -Variables that are moved into a function (or block scope) and aren't explicitly -returned get "dropped" at the end of that function. This is also what happens here. -There's a few ways to fix this, try them all if you want: -1. Make another, separate version of the data that's in `vec0` and pass that +When running this exercise for the first time, you'll notice an error about +"borrow of moved value". In Rust, when an argument is passed to a function and +it's not explicitly returned, you can't use the original variable anymore. +We call this "moving" a variable. When we pass `vec0` into `fill_vec`, it's being +"moved" into `vec1`, meaning we can't access `vec0` anymore after the fact. +Rust provides a couple of different ways to mitigate this issue, feel free to try them all: +1. You could make another, separate version of the data that's in `vec0` and pass that to `fill_vec` instead. 2. Make `fill_vec` borrow its argument instead of taking ownership of it, - and then copy the data within the function in order to return an owned - `Vec` -3. Make `fill_vec` *mutably* borrow a reference to its argument (which will need to be - mutable), modify it directly, then not return anything. Then you can get rid - of `vec1` entirely -- note that this will change what gets printed by the - first `println!`""" + and then copy the data within the function (`vec.clone()`) in order to return an owned + `Vec`. +3. Or, you could make `fill_vec` *mutably* borrow a reference to its argument (which will need to be + mutable), modify it directly, then not return anything. This means that `vec0` will change over the + course of the function, and makes `vec1` redundant (make sure to change the parameters of the `println!` + statements if you go this route) +""" [[exercises]] name = "move_semantics3" @@ -905,67 +906,6 @@ The fold method can be useful in the count_collection_iterator function. For a further challenge, consult the documentation for Iterator to find a different method that could make your code more compact than using fold.""" -# THREADS - -[[exercises]] -name = "threads1" -path = "exercises/threads/threads1.rs" -mode = "compile" -hint = """ -`JoinHandle` is a struct that is returned from a spawned thread: -https://doc.rust-lang.org/std/thread/fn.spawn.html - -A challenge with multi-threaded applications is that the main thread can -finish before the spawned threads are completed. -https://doc.rust-lang.org/book/ch16-01-threads.html#waiting-for-all-threads-to-finish-using-join-handles - -Use the JoinHandles to wait for each thread to finish and collect their results. -https://doc.rust-lang.org/std/thread/struct.JoinHandle.html -""" - -[[exercises]] -name = "threads2" -path = "exercises/threads/threads2.rs" -mode = "compile" -hint = """ -`Arc` is an Atomic Reference Counted pointer that allows safe, shared access -to **immutable** data. But we want to *change* the number of `jobs_completed` -so we'll need to also use another type that will only allow one thread to -mutate the data at a time. Take a look at this section of the book: -https://doc.rust-lang.org/book/ch16-03-shared-state.html#atomic-reference-counting-with-arct -and keep reading if you'd like more hints :) - - -Do you now have an `Arc` `Mutex` `JobStatus` at the beginning of main? Like: -`let status = Arc::new(Mutex::new(JobStatus { jobs_completed: 0 }));` -Similar to the code in the example in the book that happens after the text -that says "We can use Arc to fix this.". If not, give that a try! If you -do and would like more hints, keep reading!! - - -Make sure neither of your threads are holding onto the lock of the mutex -while they are sleeping, since this will prevent the other thread from -being allowed to get the lock. Locks are automatically released when -they go out of scope. - -If you've learned from the sample solutions, I encourage you to come -back to this exercise and try it again in a few days to reinforce -what you've learned :)""" - -[[exercises]] -name = "threads3" -path = "exercises/threads/threads3.rs" -mode = "compile" -hint = """ -An alternate way to handle concurrency between threads is to use -a mpsc (multiple producer, single consumer) channel to communicate. -With both a sending end and a receiving end, it's possible to -send values in one thread and receive them in another. -Multiple producers are possible by using clone() to create a duplicate -of the original sending end. -See https://doc.rust-lang.org/book/ch16-02-message-passing.html for more info. -""" - # SMART POINTERS [[exercises]] @@ -1028,6 +968,67 @@ Check out https://doc.rust-lang.org/std/borrow/enum.Cow.html for documentation on the `Cow` type. """ +# THREADS + +[[exercises]] +name = "threads1" +path = "exercises/threads/threads1.rs" +mode = "compile" +hint = """ +`JoinHandle` is a struct that is returned from a spawned thread: +https://doc.rust-lang.org/std/thread/fn.spawn.html + +A challenge with multi-threaded applications is that the main thread can +finish before the spawned threads are completed. +https://doc.rust-lang.org/book/ch16-01-threads.html#waiting-for-all-threads-to-finish-using-join-handles + +Use the JoinHandles to wait for each thread to finish and collect their results. +https://doc.rust-lang.org/std/thread/struct.JoinHandle.html +""" + +[[exercises]] +name = "threads2" +path = "exercises/threads/threads2.rs" +mode = "compile" +hint = """ +`Arc` is an Atomic Reference Counted pointer that allows safe, shared access +to **immutable** data. But we want to *change* the number of `jobs_completed` +so we'll need to also use another type that will only allow one thread to +mutate the data at a time. Take a look at this section of the book: +https://doc.rust-lang.org/book/ch16-03-shared-state.html#atomic-reference-counting-with-arct +and keep reading if you'd like more hints :) + + +Do you now have an `Arc` `Mutex` `JobStatus` at the beginning of main? Like: +`let status = Arc::new(Mutex::new(JobStatus { jobs_completed: 0 }));` +Similar to the code in the example in the book that happens after the text +that says "We can use Arc to fix this.". If not, give that a try! If you +do and would like more hints, keep reading!! + + +Make sure neither of your threads are holding onto the lock of the mutex +while they are sleeping, since this will prevent the other thread from +being allowed to get the lock. Locks are automatically released when +they go out of scope. + +If you've learned from the sample solutions, I encourage you to come +back to this exercise and try it again in a few days to reinforce +what you've learned :)""" + +[[exercises]] +name = "threads3" +path = "exercises/threads/threads3.rs" +mode = "compile" +hint = """ +An alternate way to handle concurrency between threads is to use +a mpsc (multiple producer, single consumer) channel to communicate. +With both a sending end and a receiving end, it's possible to +send values in one thread and receive them in another. +Multiple producers are possible by using clone() to create a duplicate +of the original sending end. +See https://doc.rust-lang.org/book/ch16-02-message-passing.html for more info. +""" + # MACROS [[exercises]] @@ -1170,4 +1171,4 @@ name = "as_ref_mut" path = "exercises/conversions/as_ref_mut.rs" mode = "test" hint = """ -Add AsRef as a trait bound to the functions.""" +Add AsRef or AsMut as a trait bound to the functions."""