From ed0f278a8f116a1f69f20bba15485f019bfe2142 Mon Sep 17 00:00:00 2001 From: mokou Date: Mon, 11 Jul 2022 12:53:49 +0200 Subject: [PATCH 01/71] chore: remove mod.rs files and exercises feature --- Cargo.lock | 2 +- Cargo.toml | 5 +---- exercises/advanced_errors/mod.rs | 2 -- exercises/clippy/mod.rs | 2 -- exercises/collections/mod.rs | 4 ---- exercises/conversions/mod.rs | 5 ----- exercises/enums/mod.rs | 3 --- exercises/error_handling/mod.rs | 6 ------ exercises/functions/mod.rs | 5 ----- exercises/generics/mod.rs | 3 --- exercises/if/mod.rs | 2 -- exercises/intro/mod.rs | 2 -- exercises/macros/mod.rs | 4 ---- exercises/mod.rs | 26 ------------------------- exercises/modules/mod.rs | 3 --- exercises/move_semantics/mod.rs | 6 ------ exercises/option/mod.rs | 3 --- exercises/primitive_types/mod.rs | 6 ------ exercises/standard_library_types/mod.rs | 7 ------- exercises/strings/mod.rs | 2 -- exercises/structs/mod.rs | 3 --- exercises/tests/mod.rs | 3 --- exercises/threads/mod.rs | 1 - exercises/traits/mod.rs | 2 -- exercises/variables/mod.rs | 6 ------ src/lib.rs | 3 --- 26 files changed, 2 insertions(+), 114 deletions(-) delete mode 100644 exercises/advanced_errors/mod.rs delete mode 100644 exercises/clippy/mod.rs delete mode 100644 exercises/collections/mod.rs delete mode 100644 exercises/conversions/mod.rs delete mode 100644 exercises/enums/mod.rs delete mode 100644 exercises/error_handling/mod.rs delete mode 100644 exercises/functions/mod.rs delete mode 100644 exercises/generics/mod.rs delete mode 100644 exercises/if/mod.rs delete mode 100644 exercises/intro/mod.rs delete mode 100644 exercises/macros/mod.rs delete mode 100644 exercises/mod.rs delete mode 100644 exercises/modules/mod.rs delete mode 100644 exercises/move_semantics/mod.rs delete mode 100644 exercises/option/mod.rs delete mode 100644 exercises/primitive_types/mod.rs delete mode 100644 exercises/standard_library_types/mod.rs delete mode 100644 exercises/strings/mod.rs delete mode 100644 exercises/structs/mod.rs delete mode 100644 exercises/tests/mod.rs delete mode 100644 exercises/threads/mod.rs delete mode 100644 exercises/traits/mod.rs delete mode 100644 exercises/variables/mod.rs delete mode 100644 src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index 6737d29c..df190ad8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -459,7 +459,7 @@ checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" [[package]] name = "rustlings" -version = "4.7.1" +version = "4.8.0" dependencies = [ "argh", "assert_cmd", diff --git a/Cargo.toml b/Cargo.toml index e356a2c2..8a3264d9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustlings" version = "4.8.0" -authors = ["mokou ", "Carol (Nichols || Goulding) "] +authors = ["Liv ", "Carol (Nichols || Goulding) "] edition = "2021" [dependencies] @@ -24,6 +24,3 @@ path = "src/main.rs" assert_cmd = "0.11.0" predicates = "1.0.1" glob = "0.3.0" - -[features] -exercises = [] diff --git a/exercises/advanced_errors/mod.rs b/exercises/advanced_errors/mod.rs deleted file mode 100644 index e33fb80d..00000000 --- a/exercises/advanced_errors/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -mod advanced_errs1; -mod advanced_errs2; diff --git a/exercises/clippy/mod.rs b/exercises/clippy/mod.rs deleted file mode 100644 index 689dc95f..00000000 --- a/exercises/clippy/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -mod clippy1; -mod clippy2; diff --git a/exercises/collections/mod.rs b/exercises/collections/mod.rs deleted file mode 100644 index f46c1424..00000000 --- a/exercises/collections/mod.rs +++ /dev/null @@ -1,4 +0,0 @@ -mod hashmap1; -mod hashmap2; -mod vec1; -mod vec2; diff --git a/exercises/conversions/mod.rs b/exercises/conversions/mod.rs deleted file mode 100644 index 69f66ae4..00000000 --- a/exercises/conversions/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -mod as_ref_mut; -mod from_into; -mod from_str; -mod try_from_into; -mod using_as; diff --git a/exercises/enums/mod.rs b/exercises/enums/mod.rs deleted file mode 100644 index a23fd6e5..00000000 --- a/exercises/enums/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -mod enums1; -mod enums2; -mod enums3; diff --git a/exercises/error_handling/mod.rs b/exercises/error_handling/mod.rs deleted file mode 100644 index 539fa23d..00000000 --- a/exercises/error_handling/mod.rs +++ /dev/null @@ -1,6 +0,0 @@ -mod errors1; -mod errors2; -mod errors3; -mod errors4; -mod errors5; -mod errors6; diff --git a/exercises/functions/mod.rs b/exercises/functions/mod.rs deleted file mode 100644 index 445b6f58..00000000 --- a/exercises/functions/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -mod functions1; -mod functions2; -mod functions3; -mod functions4; -mod functions5; diff --git a/exercises/generics/mod.rs b/exercises/generics/mod.rs deleted file mode 100644 index 5b93555c..00000000 --- a/exercises/generics/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -mod generics1; -mod generics2; -mod generics3; diff --git a/exercises/if/mod.rs b/exercises/if/mod.rs deleted file mode 100644 index c5d02445..00000000 --- a/exercises/if/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -mod if1; -mod if2; diff --git a/exercises/intro/mod.rs b/exercises/intro/mod.rs deleted file mode 100644 index 445c47ab..00000000 --- a/exercises/intro/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -mod intro1; -mod intro2; diff --git a/exercises/macros/mod.rs b/exercises/macros/mod.rs deleted file mode 100644 index 9f65acf5..00000000 --- a/exercises/macros/mod.rs +++ /dev/null @@ -1,4 +0,0 @@ -mod macros1; -mod macros2; -mod macros3; -mod macros4; diff --git a/exercises/mod.rs b/exercises/mod.rs deleted file mode 100644 index 6a143b56..00000000 --- a/exercises/mod.rs +++ /dev/null @@ -1,26 +0,0 @@ -mod advanced_errors; -mod clippy; -mod collections; -mod conversions; -mod enums; -mod error_handling; -mod functions; -mod generics; -mod r#if; -mod intro; -mod macros; -mod modules; -mod move_semantics; -mod option; -mod primitive_types; -mod quiz1; -mod quiz2; -mod quiz3; -mod quiz4; -mod standard_library_types; -mod strings; -mod structs; -mod tests; -mod threads; -mod traits; -mod variables; diff --git a/exercises/modules/mod.rs b/exercises/modules/mod.rs deleted file mode 100644 index 35f96af5..00000000 --- a/exercises/modules/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -mod modules1; -mod modules2; -mod modules3; diff --git a/exercises/move_semantics/mod.rs b/exercises/move_semantics/mod.rs deleted file mode 100644 index e8eecf0a..00000000 --- a/exercises/move_semantics/mod.rs +++ /dev/null @@ -1,6 +0,0 @@ -mod move_semantics1; -mod move_semantics2; -mod move_semantics3; -mod move_semantics4; -mod move_semantics5; -mod move_semantics6; diff --git a/exercises/option/mod.rs b/exercises/option/mod.rs deleted file mode 100644 index b3cdb13d..00000000 --- a/exercises/option/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -mod option1; -mod option2; -mod option3; diff --git a/exercises/primitive_types/mod.rs b/exercises/primitive_types/mod.rs deleted file mode 100644 index 23355239..00000000 --- a/exercises/primitive_types/mod.rs +++ /dev/null @@ -1,6 +0,0 @@ -mod primitive_types1; -mod primitive_types2; -mod primitive_types3; -mod primitive_types4; -mod primitive_types5; -mod primitive_types6; diff --git a/exercises/standard_library_types/mod.rs b/exercises/standard_library_types/mod.rs deleted file mode 100644 index b03acb92..00000000 --- a/exercises/standard_library_types/mod.rs +++ /dev/null @@ -1,7 +0,0 @@ -mod arc1; -mod box1; -mod iterators1; -mod iterators2; -mod iterators3; -mod iterators4; -mod iterators5; diff --git a/exercises/strings/mod.rs b/exercises/strings/mod.rs deleted file mode 100644 index b1b460bc..00000000 --- a/exercises/strings/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -mod strings1; -mod strings2; diff --git a/exercises/structs/mod.rs b/exercises/structs/mod.rs deleted file mode 100644 index 214fed16..00000000 --- a/exercises/structs/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -mod structs1; -mod structs2; -mod structs3; diff --git a/exercises/tests/mod.rs b/exercises/tests/mod.rs deleted file mode 100644 index 489541be..00000000 --- a/exercises/tests/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -mod tests1; -mod tests2; -mod tests3; diff --git a/exercises/threads/mod.rs b/exercises/threads/mod.rs deleted file mode 100644 index 24d54007..00000000 --- a/exercises/threads/mod.rs +++ /dev/null @@ -1 +0,0 @@ -mod threads1; diff --git a/exercises/traits/mod.rs b/exercises/traits/mod.rs deleted file mode 100644 index 6f0a9c3f..00000000 --- a/exercises/traits/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -mod traits1; -mod traits2; diff --git a/exercises/variables/mod.rs b/exercises/variables/mod.rs deleted file mode 100644 index a25f477e..00000000 --- a/exercises/variables/mod.rs +++ /dev/null @@ -1,6 +0,0 @@ -mod variables1; -mod variables2; -mod variables3; -mod variables4; -mod variables5; -mod variables6; diff --git a/src/lib.rs b/src/lib.rs deleted file mode 100644 index 82c1e7e4..00000000 --- a/src/lib.rs +++ /dev/null @@ -1,3 +0,0 @@ -#[cfg(feature = "exercises")] -#[path = "../exercises/mod.rs"] -mod exercises; From 0aee54a82b699d1e46d190b21d03101e8522b242 Mon Sep 17 00:00:00 2001 From: mokou Date: Mon, 11 Jul 2022 13:12:47 +0200 Subject: [PATCH 02/71] chore: unify hint language use --- info.toml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/info.toml b/info.toml index a9608e65..232908fc 100644 --- a/info.toml +++ b/info.toml @@ -21,7 +21,7 @@ name = "variables1" path = "exercises/variables/variables1.rs" mode = "compile" hint = """ -Hint: The declaration on line 8 is missing a keyword that is needed in Rust +The declaration on line 8 is missing a keyword that is needed in Rust to create a new variable binding.""" [[exercises]] @@ -360,14 +360,14 @@ name = "enums1" path = "exercises/enums/enums1.rs" mode = "compile" hint = """ -Hint: The declaration of the enumeration type has not been defined yet.""" +The declaration of the enumeration type has not been defined yet.""" [[exercises]] name = "enums2" path = "exercises/enums/enums2.rs" mode = "compile" hint = """ -Hint: you can create enumerations that have different variants with different types +You can create enumerations that have different variants with different types such as no data, anonymous structs, a single string, tuples, ...etc""" [[exercises]] @@ -536,7 +536,7 @@ name = "errors5" path = "exercises/error_handling/errors5.rs" mode = "compile" hint = """ -Hint: There are two different possible `Result` types produced within +There are two different possible `Result` types produced within `main()`, which are propagated using `?` operators. How do we declare a return type from `main()` that allows both? @@ -980,7 +980,7 @@ or an Err with an error if the string is not valid. This is almost like the `from_into` exercise, but returning errors instead of falling back to a default value. -Hint: Look at the test cases to see which error variants to return. +Look at the test cases to see which error variants to return. Another hint: You can use the `map_err` method of `Result` with a function or a closure to wrap the error from `parse::`. @@ -998,7 +998,7 @@ hint = """ Follow the steps provided right before the `TryFrom` implementation. You can also use the example at https://doc.rust-lang.org/std/convert/trait.TryFrom.html -Hint: Is there an implementation of `TryFrom` in the standard library that +Is there an implementation of `TryFrom` in the standard library that can both do the required integer conversion and check the range of the input? Another hint: Look at the test cases to see which error variants to return. From 0ded8a90c026bf5c6129d96956183c641ac1ad20 Mon Sep 17 00:00:00 2001 From: mokou Date: Mon, 11 Jul 2022 13:19:19 +0200 Subject: [PATCH 03/71] feat(intro1): add more hints --- exercises/intro/intro1.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/exercises/intro/intro1.rs b/exercises/intro/intro1.rs index 1c4582de..5d4becf3 100644 --- a/exercises/intro/intro1.rs +++ b/exercises/intro/intro1.rs @@ -4,6 +4,10 @@ // after you already figured it out. If you got everything working and feel // ready for the next exercise, remove the `I AM NOT DONE` comment below. // Execute the command `rustlings hint intro1` for a hint. +// +// If you're running this using `rustlings watch`: The exercise file will be reloaded +// when you change one of the lines below! Try adding a `println!` line, or try changing +// what it outputs in your terminal. Try removing a semicolon and see what happens! // I AM NOT DONE @@ -20,4 +24,7 @@ fn main() { println!("This exercise compiles successfully. The remaining exercises contain a compiler"); println!("or logic error. The central concept behind Rustlings is to fix these errors and"); println!("solve the exercises. Good luck!"); + println!(); + println!("The source for this exercise is in `exercises/intro/intro1.rs`. Have a look!"); + println!("Going forward, the source of the exercises will always be in the success/failure output."); } From 9ed4b0683edcf73ab0fbdcfe479a82898e6d5e42 Mon Sep 17 00:00:00 2001 From: mokou Date: Mon, 11 Jul 2022 13:20:18 +0200 Subject: [PATCH 04/71] fix(intro1): link to exercise file in hint --- info.toml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/info.toml b/info.toml index 232908fc..f3a52177 100644 --- a/info.toml +++ b/info.toml @@ -5,7 +5,8 @@ name = "intro1" path = "exercises/intro/intro1.rs" mode = "compile" hint = """ -Remove the I AM NOT DONE comment to move on to the next exercise.""" +Remove the I AM NOT DONE comment in the exercises/intro/intro1.rs file +to move on to the next exercise.""" [[exercises]] name = "intro2" From c3c21ad91fd66bcffedb85f542c1c830e1a7cdc0 Mon Sep 17 00:00:00 2001 From: mokou Date: Mon, 11 Jul 2022 13:35:16 +0200 Subject: [PATCH 05/71] fix(intro): clarify hint usage --- exercises/intro/intro1.rs | 2 +- exercises/intro/intro2.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/exercises/intro/intro1.rs b/exercises/intro/intro1.rs index 5d4becf3..45c5acba 100644 --- a/exercises/intro/intro1.rs +++ b/exercises/intro/intro1.rs @@ -3,7 +3,7 @@ // We sometimes encourage you to keep trying things on a given exercise, even // after you already figured it out. If you got everything working and feel // ready for the next exercise, remove the `I AM NOT DONE` comment below. -// Execute the command `rustlings hint intro1` for a hint. +// Execute `rustlings hint intro1` or use the `hint` watch subcommand for a hint. // // If you're running this using `rustlings watch`: The exercise file will be reloaded // when you change one of the lines below! Try adding a `println!` line, or try changing diff --git a/exercises/intro/intro2.rs b/exercises/intro/intro2.rs index 97a073f0..efc1af20 100644 --- a/exercises/intro/intro2.rs +++ b/exercises/intro/intro2.rs @@ -1,6 +1,6 @@ // intro2.rs // Make the code print a greeting to the world. -// Execute `rustlings hint intro2` for a hint. +// Execute `rustlings hint intro2` or use the `hint` watch subcommand for a hint. // I AM NOT DONE From 81edc4234fbe40eee34f83bbc2995c69f9e1e07c Mon Sep 17 00:00:00 2001 From: mokou Date: Mon, 11 Jul 2022 13:43:41 +0200 Subject: [PATCH 06/71] fix(variables): reorder and redo hint texts --- exercises/variables/variables1.rs | 2 +- exercises/variables/variables2.rs | 6 +++--- exercises/variables/variables3.rs | 6 ++---- exercises/variables/variables4.rs | 6 ++++-- exercises/variables/variables5.rs | 2 +- exercises/variables/variables6.rs | 2 +- info.toml | 16 ++++++++-------- 7 files changed, 20 insertions(+), 20 deletions(-) diff --git a/exercises/variables/variables1.rs b/exercises/variables/variables1.rs index d1af8311..f4d182ac 100644 --- a/exercises/variables/variables1.rs +++ b/exercises/variables/variables1.rs @@ -1,6 +1,6 @@ // variables1.rs // Make me compile! -// Execute the command `rustlings hint variables1` if you want a hint :) +// Execute `rustlings hint variables1` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/exercises/variables/variables2.rs b/exercises/variables/variables2.rs index 7774a8fb..641aeb8e 100644 --- a/exercises/variables/variables2.rs +++ b/exercises/variables/variables2.rs @@ -1,13 +1,13 @@ // variables2.rs -// Make me compile! Execute the command `rustlings hint variables2` if you want a hint :) +// Execute `rustlings hint variables2` or use the `hint` watch subcommand for a hint. // I AM NOT DONE fn main() { let x; if x == 10 { - println!("Ten!"); + println!("x is ten!"); } else { - println!("Not ten!"); + println!("x is not ten!"); } } diff --git a/exercises/variables/variables3.rs b/exercises/variables/variables3.rs index 30ec48ff..819b1bc7 100644 --- a/exercises/variables/variables3.rs +++ b/exercises/variables/variables3.rs @@ -1,11 +1,9 @@ // variables3.rs -// Make me compile! Execute the command `rustlings hint variables3` if you want a hint :) +// Execute `rustlings hint variables3` or use the `hint` watch subcommand for a hint. // I AM NOT DONE fn main() { - let x = 3; - println!("Number {}", x); - x = 5; // don't change this line + let x: i32; println!("Number {}", x); } diff --git a/exercises/variables/variables4.rs b/exercises/variables/variables4.rs index 77f1e9ab..54491b0a 100644 --- a/exercises/variables/variables4.rs +++ b/exercises/variables/variables4.rs @@ -1,9 +1,11 @@ // variables4.rs -// Make me compile! Execute the command `rustlings hint variables4` if you want a hint :) +// Execute `rustlings hint variables4` or use the `hint` watch subcommand for a hint. // I AM NOT DONE fn main() { - let x: i32; + let x = 3; + println!("Number {}", x); + x = 5; // don't change this line println!("Number {}", x); } diff --git a/exercises/variables/variables5.rs b/exercises/variables/variables5.rs index 175eebb3..7042d6fa 100644 --- a/exercises/variables/variables5.rs +++ b/exercises/variables/variables5.rs @@ -1,5 +1,5 @@ // variables5.rs -// Make me compile! Execute the command `rustlings hint variables5` if you want a hint :) +// Execute `rustlings hint variables5` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/exercises/variables/variables6.rs b/exercises/variables/variables6.rs index 98666914..a8520122 100644 --- a/exercises/variables/variables6.rs +++ b/exercises/variables/variables6.rs @@ -1,5 +1,5 @@ // variables6.rs -// Make me compile! Execute the command `rustlings hint variables6` if you want a hint :) +// Execute `rustlings hint variables6` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/info.toml b/info.toml index f3a52177..c5f22f92 100644 --- a/info.toml +++ b/info.toml @@ -43,20 +43,20 @@ name = "variables3" path = "exercises/variables/variables3.rs" mode = "compile" hint = """ -In Rust, variable bindings are immutable by default. But here we're trying -to reassign a different value to x! There's a keyword we can use to make -a variable binding mutable instead.""" +Oops! In this exercise, we have a variable binding that we've created on +line 7, and we're trying to use it on line 8, but we haven't given it a +value. We can't print out something that isn't there; try giving x a value! +This is an error that can cause bugs that's very easy to make in any +programming language -- thankfully the Rust compiler has caught this for us!""" [[exercises]] name = "variables4" path = "exercises/variables/variables4.rs" mode = "compile" hint = """ -Oops! In this exercise, we have a variable binding that we've created on -line 7, and we're trying to use it on line 8, but we haven't given it a -value. We can't print out something that isn't there; try giving x a value! -This is an error that can cause bugs that's very easy to make in any -programming language -- thankfully the Rust compiler has caught this for us!""" +In Rust, variable bindings are immutable by default. But here we're trying +to reassign a different value to x! There's a keyword we can use to make +a variable binding mutable instead.""" [[exercises]] name = "variables5" From 60410cfd2ea4f819f633e3c69efe916d3f825536 Mon Sep 17 00:00:00 2001 From: gavin Date: Sun, 20 Feb 2022 10:53:51 +0530 Subject: [PATCH 07/71] fix(variables5): Add nudge for shadowing variable --- exercises/variables/variables5.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exercises/variables/variables5.rs b/exercises/variables/variables5.rs index 7042d6fa..0e670d2a 100644 --- a/exercises/variables/variables5.rs +++ b/exercises/variables/variables5.rs @@ -6,6 +6,6 @@ fn main() { let number = "T-H-R-E-E"; // don't change this line println!("Spell a Number : {}", number); - number = 3; + number = 3; // don't rename this variable println!("Number plus two is : {}", number + 2); } From 9688609d0892757b2f0ce769367e7c5821e3f94c Mon Sep 17 00:00:00 2001 From: Cooper Gillan Date: Fri, 25 Feb 2022 02:33:45 +0000 Subject: [PATCH 08/71] chore: Update variables6.rs hint book link, wording While the included link for variables6 does navigate to the correct page, the header in the link itself does not actually exist so it only loads the top of the page. There is, however, some text about the difference between variables and constants in the "Constants" section, so reword the hint some and update the link. --- info.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/info.toml b/info.toml index c5f22f92..042172de 100644 --- a/info.toml +++ b/info.toml @@ -84,7 +84,7 @@ Constants are always immutable and they are declared with keyword 'const' rather than keyword 'let'. Constants types must also always be annotated. -Read more about constants under 'Differences Between Variables and Constants' in the book's section 'Variables and Mutability': +Read more about constants and the differences between variables and constants under 'Constants' in the book's section 'Variables and Mutability': https://doc.rust-lang.org/book/ch03-01-variables-and-mutability.html#constants """ From b3ec8fe0223eda6ce31e72d464b6a56d71b2204f Mon Sep 17 00:00:00 2001 From: Cooper Gillan Date: Fri, 25 Feb 2022 02:35:43 +0000 Subject: [PATCH 09/71] chore: Tweak punctuation in variables6.rs hint While the meaning is still obvious as is, it makes a little more sense to use a colon here =) --- info.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/info.toml b/info.toml index 042172de..d7906431 100644 --- a/info.toml +++ b/info.toml @@ -79,7 +79,7 @@ path = "exercises/variables/variables6.rs" mode = "compile" hint = """ We know about variables and mutability, but there is another important type of -variable available; constants. +variable available: constants. Constants are always immutable and they are declared with keyword 'const' rather than keyword 'let'. Constants types must also always be annotated. From 093a525450bd1d0092d91bb90969bffab2df55a9 Mon Sep 17 00:00:00 2001 From: mokou Date: Mon, 11 Jul 2022 14:00:12 +0200 Subject: [PATCH 10/71] fix(functions): clarify README wording --- exercises/functions/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/exercises/functions/README.md b/exercises/functions/README.md index 66547bd4..6662d0da 100644 --- a/exercises/functions/README.md +++ b/exercises/functions/README.md @@ -1,6 +1,7 @@ # Functions -Here, you'll learn how to write functions and how Rust's compiler can trace things way back. +Here, you'll learn how to write functions and how the Rust compiler can help you debug errors even +in more complex code. ## Further information From 742fb08e010725868ebdce41038461088d95a3d9 Mon Sep 17 00:00:00 2001 From: mokou Date: Tue, 12 Jul 2022 11:08:29 +0200 Subject: [PATCH 11/71] feat(functions): more small fixes --- exercises/functions/functions1.rs | 2 +- exercises/functions/functions2.rs | 2 +- exercises/functions/functions3.rs | 2 +- exercises/functions/functions4.rs | 5 ++++- exercises/functions/functions5.rs | 4 ++-- info.toml | 9 +++++++-- 6 files changed, 16 insertions(+), 8 deletions(-) diff --git a/exercises/functions/functions1.rs b/exercises/functions/functions1.rs index 31125278..03d8af70 100644 --- a/exercises/functions/functions1.rs +++ b/exercises/functions/functions1.rs @@ -1,5 +1,5 @@ // functions1.rs -// Make me compile! Execute `rustlings hint functions1` for hints :) +// Execute `rustlings hint functions1` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/exercises/functions/functions2.rs b/exercises/functions/functions2.rs index 5721a172..7d40a578 100644 --- a/exercises/functions/functions2.rs +++ b/exercises/functions/functions2.rs @@ -1,5 +1,5 @@ // functions2.rs -// Make me compile! Execute `rustlings hint functions2` for hints :) +// Execute `rustlings hint functions2` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/exercises/functions/functions3.rs b/exercises/functions/functions3.rs index ed5f839f..3b9e585b 100644 --- a/exercises/functions/functions3.rs +++ b/exercises/functions/functions3.rs @@ -1,5 +1,5 @@ // functions3.rs -// Make me compile! Execute `rustlings hint functions3` for hints :) +// Execute `rustlings hint functions3` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/exercises/functions/functions4.rs b/exercises/functions/functions4.rs index 58637e4c..65d5be4f 100644 --- a/exercises/functions/functions4.rs +++ b/exercises/functions/functions4.rs @@ -1,8 +1,11 @@ // functions4.rs -// Make me compile! Execute `rustlings hint functions4` for hints :) +// Execute `rustlings hint functions4` or use the `hint` watch subcommand for a hint. // This store is having a sale where if the price is an even number, you get // 10 Rustbucks off, but if it's an odd number, it's 3 Rustbucks off. +// (Don't worry about the function bodies themselves, we're only interested +// in the signatures for now. If anything, this is a good way to peek ahead +// to future exercises!) // I AM NOT DONE diff --git a/exercises/functions/functions5.rs b/exercises/functions/functions5.rs index d22aa6c8..5d762961 100644 --- a/exercises/functions/functions5.rs +++ b/exercises/functions/functions5.rs @@ -1,11 +1,11 @@ // functions5.rs -// Make me compile! Execute `rustlings hint functions5` for hints :) +// Execute `rustlings hint functions5` or use the `hint` watch subcommand for a hint. // I AM NOT DONE fn main() { let answer = square(3); - println!("The answer is {}", answer); + println!("The square of 3 is {}", answer); } fn square(num: i32) -> i32 { diff --git a/info.toml b/info.toml index d7906431..84df9111 100644 --- a/info.toml +++ b/info.toml @@ -114,7 +114,9 @@ path = "exercises/functions/functions3.rs" mode = "compile" hint = """ This time, the function *declaration* is okay, but there's something wrong -with the place where we're calling the function.""" +with the place where we're calling the function. +As a reminder, you can freely play around with different solutions in Rustlings! +Watch mode will only jump to the next exercise if you remove the I AM NOT DONE comment.""" [[exercises]] name = "functions4" @@ -123,7 +125,10 @@ mode = "compile" hint = """ The error message points to line 14 and says it expects a type after the `->`. This is where the function's return type should be-- take a look at -the `is_even` function for an example!""" +the `is_even` function for an example! + +Also: Did you figure out that, technically, u32 would be the more fitting type +for the prices here, since they can't be negative? If so, kudos!""" [[exercises]] name = "functions5" From 4868d18ea315f15ad007086f218c8a1ee68a8eb4 Mon Sep 17 00:00:00 2001 From: mokou Date: Tue, 12 Jul 2022 11:10:08 +0200 Subject: [PATCH 12/71] feat(if): replace hints --- exercises/if/README.md | 2 +- exercises/if/if1.rs | 2 +- exercises/if/if2.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/exercises/if/README.md b/exercises/if/README.md index 528d9886..b52c3922 100644 --- a/exercises/if/README.md +++ b/exercises/if/README.md @@ -1,6 +1,6 @@ # If -`if`, the most basic type of control flow, is what you'll learn here. +`if`, the most basic (but still surprisingly versatile!) type of control flow, is what you'll learn here. ## Further information diff --git a/exercises/if/if1.rs b/exercises/if/if1.rs index 90867545..587e03f8 100644 --- a/exercises/if/if1.rs +++ b/exercises/if/if1.rs @@ -1,4 +1,5 @@ // if1.rs +// Execute `rustlings hint if1` or use the `hint` watch subcommand for a hint. // I AM NOT DONE @@ -7,7 +8,6 @@ pub fn bigger(a: i32, b: i32) -> i32 { // Do not use: // - another function call // - additional variables - // Execute `rustlings hint if1` for hints } // Don't mind this for now :) diff --git a/exercises/if/if2.rs b/exercises/if/if2.rs index 80effbdf..6fed6f81 100644 --- a/exercises/if/if2.rs +++ b/exercises/if/if2.rs @@ -2,7 +2,7 @@ // Step 1: Make me compile! // Step 2: Get the bar_for_fuzz and default_to_baz tests passing! -// Execute the command `rustlings hint if2` if you want a hint :) +// Execute `rustlings hint if2` or use the `hint` watch subcommand for a hint. // I AM NOT DONE From 5812f1f27b0e3c2eed6e4606635bb810d0a5727e Mon Sep 17 00:00:00 2001 From: Adam Sherwood Date: Sun, 20 Feb 2022 16:15:56 +0100 Subject: [PATCH 13/71] fix(if2): Rename if2 exercise function to foo_if_fizz. The reasoning here is pretty straightforward: you don't say "Hungry, if eat." That doesn't make sense. We want to get "foo" back if given "fizz", so it seems this makes far more sense as "Eat, if hungry," or in this case, return `foo_if_fizz` is given. --- exercises/if/if2.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/exercises/if/if2.rs b/exercises/if/if2.rs index 6fed6f81..effddbb6 100644 --- a/exercises/if/if2.rs +++ b/exercises/if/if2.rs @@ -6,7 +6,7 @@ // I AM NOT DONE -pub fn fizz_if_foo(fizzish: &str) -> &str { +pub fn foo_if_fizz(fizzish: &str) -> &str { if fizzish == "fizz" { "foo" } else { @@ -21,16 +21,16 @@ mod tests { #[test] fn foo_for_fizz() { - assert_eq!(fizz_if_foo("fizz"), "foo") + assert_eq!(foo_if_fizz("fizz"), "foo") } #[test] fn bar_for_fuzz() { - assert_eq!(fizz_if_foo("fuzz"), "bar") + assert_eq!(foo_if_fizz("fuzz"), "bar") } #[test] fn default_to_baz() { - assert_eq!(fizz_if_foo("literally anything"), "baz") + assert_eq!(foo_if_fizz("literally anything"), "baz") } } From 6020ec1fe21aa1763821940dcc7029b99fb9d00a Mon Sep 17 00:00:00 2001 From: mokou Date: Tue, 12 Jul 2022 14:53:56 +0200 Subject: [PATCH 14/71] feat: reorder vec and primtypes before moving --- info.toml | 177 +++++++++++++++++++++++++++--------------------------- 1 file changed, 90 insertions(+), 87 deletions(-) diff --git a/info.toml b/info.toml index 84df9111..717ea95e 100644 --- a/info.toml +++ b/info.toml @@ -175,6 +175,96 @@ path = "exercises/quiz1.rs" mode = "test" hint = "No hints this time ;)" +# PRIMITIVE TYPES + +[[exercises]] +name = "primitive_types1" +path = "exercises/primitive_types/primitive_types1.rs" +mode = "compile" +hint = "No hints this time ;)" + +[[exercises]] +name = "primitive_types2" +path = "exercises/primitive_types/primitive_types2.rs" +mode = "compile" +hint = "No hints this time ;)" + +[[exercises]] +name = "primitive_types3" +path = "exercises/primitive_types/primitive_types3.rs" +mode = "compile" +hint = """ +There's a shorthand to initialize Arrays with a certain size that does not +require you to type in 100 items (but you certainly can if you want!). +For example, you can do: +let array = ["Are we there yet?"; 10]; + +Bonus: what are some other things you could have that would return true +for `a.len() >= 100`?""" + +[[exercises]] +name = "primitive_types4" +path = "exercises/primitive_types/primitive_types4.rs" +mode = "test" +hint = """ +Take a look at the Understanding Ownership -> Slices -> Other Slices section of the book: +https://doc.rust-lang.org/book/ch04-03-slices.html +and use the starting and ending indices of the items in the Array +that you want to end up in the slice. + +If you're curious why the first argument of `assert_eq!` does not +have an ampersand for a reference since the second argument is a +reference, take a look at the coercion chapter of the nomicon: +https://doc.rust-lang.org/nomicon/coercions.html""" + +[[exercises]] +name = "primitive_types5" +path = "exercises/primitive_types/primitive_types5.rs" +mode = "compile" +hint = """ +Take a look at the Data Types -> The Tuple Type section of the book: +https://doc.rust-lang.org/book/ch03-02-data-types.html#the-tuple-type +Particularly the part about destructuring (second to last example in the section). +You'll need to make a pattern to bind `name` and `age` to the appropriate parts +of the tuple. You can do it!!""" + +[[exercises]] +name = "primitive_types6" +path = "exercises/primitive_types/primitive_types6.rs" +mode = "test" +hint = """ +While you could use a destructuring `let` for the tuple here, try +indexing into it instead, as explained in the last example of the +Data Types -> The Tuple Type section of the book: +https://doc.rust-lang.org/book/ch03-02-data-types.html#the-tuple-type +Now you have another tool in your toolbox!""" + +# VECS + +[[exercises]] +name = "vec1" +path = "exercises/collections/vec1.rs" +mode = "test" +hint = """ +In Rust, there are two ways to define a Vector. +1. One way is to use the `Vec::new()` function to create a new vector + and fill it with the `push()` method. +2. The second way, which is simpler is to use the `vec![]` macro and + define your elements inside the square brackets. +Check this chapter: https://doc.rust-lang.org/stable/book/ch08-01-vectors.html +of the Rust book to learn more. +""" + +[[exercises]] +name = "vec2" +path = "exercises/collections/vec2.rs" +mode = "test" +hint = """ +Hint 1: `i` is each element from the Vec as they are being iterated. + Can you try multiplying this? +Hint 2: Check the suggestion from the compiler error ;) +""" + # MOVE SEMANTICS [[exercises]] @@ -258,69 +348,6 @@ Can you figure out how? Another hint: it has to do with the `&` character.""" -# PRIMITIVE TYPES - -[[exercises]] -name = "primitive_types1" -path = "exercises/primitive_types/primitive_types1.rs" -mode = "compile" -hint = "No hints this time ;)" - -[[exercises]] -name = "primitive_types2" -path = "exercises/primitive_types/primitive_types2.rs" -mode = "compile" -hint = "No hints this time ;)" - -[[exercises]] -name = "primitive_types3" -path = "exercises/primitive_types/primitive_types3.rs" -mode = "compile" -hint = """ -There's a shorthand to initialize Arrays with a certain size that does not -require you to type in 100 items (but you certainly can if you want!). -For example, you can do: -let array = ["Are we there yet?"; 10]; - -Bonus: what are some other things you could have that would return true -for `a.len() >= 100`?""" - -[[exercises]] -name = "primitive_types4" -path = "exercises/primitive_types/primitive_types4.rs" -mode = "test" -hint = """ -Take a look at the Understanding Ownership -> Slices -> Other Slices section of the book: -https://doc.rust-lang.org/book/ch04-03-slices.html -and use the starting and ending indices of the items in the Array -that you want to end up in the slice. - -If you're curious why the first argument of `assert_eq!` does not -have an ampersand for a reference since the second argument is a -reference, take a look at the Deref coercions section of the book: -https://doc.rust-lang.org/book/ch15-02-deref.html""" - -[[exercises]] -name = "primitive_types5" -path = "exercises/primitive_types/primitive_types5.rs" -mode = "compile" -hint = """ -Take a look at the Data Types -> The Tuple Type section of the book: -https://doc.rust-lang.org/book/ch03-02-data-types.html#the-tuple-type -Particularly the part about destructuring (second to last example in the section). -You'll need to make a pattern to bind `name` and `age` to the appropriate parts -of the tuple. You can do it!!""" - -[[exercises]] -name = "primitive_types6" -path = "exercises/primitive_types/primitive_types6.rs" -mode = "test" -hint = """ -While you could use a destructuring `let` for the tuple here, try -indexing into it instead, as explained in the last example of the -Data Types -> The Tuple Type section of the book: -https://doc.rust-lang.org/book/ch03-02-data-types.html#the-tuple-type -Now you have another tool in your toolbox!""" # STRUCTS @@ -414,30 +441,6 @@ operator to bring these two in using only one line.""" # COLLECTIONS -[[exercises]] -name = "vec1" -path = "exercises/collections/vec1.rs" -mode = "test" -hint = """ -In Rust, there are two ways to define a Vector. -1. One way is to use the `Vec::new()` function to create a new vector - and fill it with the `push()` method. -2. The second way, which is simpler is to use the `vec![]` macro and - define your elements inside the square brackets. -Check this chapter: https://doc.rust-lang.org/stable/book/ch08-01-vectors.html -of the Rust book to learn more. -""" - -[[exercises]] -name = "vec2" -path = "exercises/collections/vec2.rs" -mode = "test" -hint = """ -Hint 1: `i` is each element from the Vec as they are being iterated. - Can you try multiplying this? -Hint 2: Check the suggestion from the compiler error ;) -""" - [[exercises]] name = "hashmap1" path = "exercises/collections/hashmap1.rs" From 7af12ba9aa45b57730b92cc00c3ddaa1527eb31f Mon Sep 17 00:00:00 2001 From: mokou Date: Tue, 12 Jul 2022 14:54:12 +0200 Subject: [PATCH 15/71] feat(primitive_types): fixups --- exercises/primitive_types/primitive_types1.rs | 1 + exercises/primitive_types/primitive_types2.rs | 2 ++ exercises/primitive_types/primitive_types3.rs | 2 +- exercises/primitive_types/primitive_types4.rs | 2 +- exercises/primitive_types/primitive_types5.rs | 2 +- 5 files changed, 6 insertions(+), 3 deletions(-) diff --git a/exercises/primitive_types/primitive_types1.rs b/exercises/primitive_types/primitive_types1.rs index 09121392..de0d08a6 100644 --- a/exercises/primitive_types/primitive_types1.rs +++ b/exercises/primitive_types/primitive_types1.rs @@ -4,6 +4,7 @@ // I AM NOT DONE +#[test] fn main() { // Booleans (`bool`) diff --git a/exercises/primitive_types/primitive_types2.rs b/exercises/primitive_types/primitive_types2.rs index 6576a4d5..8730baab 100644 --- a/exercises/primitive_types/primitive_types2.rs +++ b/exercises/primitive_types/primitive_types2.rs @@ -7,6 +7,8 @@ fn main() { // Characters (`char`) + // Note the _single_ quotes, these are different from the double quotes + // you've been seeing around. let my_first_initial = 'C'; if my_first_initial.is_alphabetic() { println!("Alphabetical!"); diff --git a/exercises/primitive_types/primitive_types3.rs b/exercises/primitive_types/primitive_types3.rs index aaa518be..fa7d019a 100644 --- a/exercises/primitive_types/primitive_types3.rs +++ b/exercises/primitive_types/primitive_types3.rs @@ -1,6 +1,6 @@ // primitive_types3.rs // Create an array with at least 100 elements in it where the ??? is. -// Execute `rustlings hint primitive_types3` for hints! +// Execute `rustlings hint primitive_types3` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/exercises/primitive_types/primitive_types4.rs b/exercises/primitive_types/primitive_types4.rs index 10b553e9..71fa243c 100644 --- a/exercises/primitive_types/primitive_types4.rs +++ b/exercises/primitive_types/primitive_types4.rs @@ -1,6 +1,6 @@ // primitive_types4.rs // Get a slice out of Array a where the ??? is so that the test passes. -// Execute `rustlings hint primitive_types4` for hints!! +// Execute `rustlings hint primitive_types4` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/exercises/primitive_types/primitive_types5.rs b/exercises/primitive_types/primitive_types5.rs index 680d8d23..4fd9141f 100644 --- a/exercises/primitive_types/primitive_types5.rs +++ b/exercises/primitive_types/primitive_types5.rs @@ -1,6 +1,6 @@ // primitive_types5.rs // Destructure the `cat` tuple so that the println will work. -// Execute `rustlings hint primitive_types5` for hints! +// Execute `rustlings hint primitive_types5` or use the `hint` watch subcommand for a hint. // I AM NOT DONE From 8e1f617d3402cb05b05c6737f60fbbfe74da4d78 Mon Sep 17 00:00:00 2001 From: mokou Date: Tue, 12 Jul 2022 15:05:47 +0200 Subject: [PATCH 16/71] feat(vec): update vec exercises --- exercises/collections/vec1.rs | 2 +- exercises/collections/vec2.rs | 20 ++++++++++++++++++-- info.toml | 12 +++++++++--- 3 files changed, 28 insertions(+), 6 deletions(-) diff --git a/exercises/collections/vec1.rs b/exercises/collections/vec1.rs index b144fb94..c26f5691 100644 --- a/exercises/collections/vec1.rs +++ b/exercises/collections/vec1.rs @@ -2,7 +2,7 @@ // Your task is to create a `Vec` which holds the exact same elements // as in the array `a`. // Make me compile and pass the test! -// Execute the command `rustlings hint vec1` if you need hints. +// Execute `rustlings hint vec1` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/exercises/collections/vec2.rs b/exercises/collections/vec2.rs index 6595e401..db37d1d6 100644 --- a/exercises/collections/vec2.rs +++ b/exercises/collections/vec2.rs @@ -4,8 +4,7 @@ // // Make me pass the test! // -// Execute the command `rustlings hint vec2` if you need -// hints. +// Execute `rustlings hint vec2` or use the `hint` watch subcommand for a hint. // I AM NOT DONE @@ -13,12 +12,21 @@ fn vec_loop(mut v: Vec) -> Vec { for i in v.iter_mut() { // TODO: Fill this up so that each element in the Vec `v` is // multiplied by 2. + ??? } // At this point, `v` should be equal to [4, 8, 12, 16, 20]. v } +fn vec_map(v: &Vec) -> Vec { + v.iter().map(|num| { + // TODO: Do the same thing as above - but instead of mutating the + // Vec, you can just return the new number! + ??? + }).collect() +} + #[cfg(test)] mod tests { use super::*; @@ -30,4 +38,12 @@ mod tests { assert_eq!(ans, v.iter().map(|x| x * 2).collect::>()); } + + #[test] + fn test_vec_map() { + let v: Vec = (1..).filter(|x| x % 2 == 0).take(5).collect(); + let ans = vec_map(&v); + + assert_eq!(ans, v.iter().map(|x| x * 2).collect::>()); + } } diff --git a/info.toml b/info.toml index 717ea95e..af4861c2 100644 --- a/info.toml +++ b/info.toml @@ -260,9 +260,15 @@ name = "vec2" path = "exercises/collections/vec2.rs" mode = "test" hint = """ -Hint 1: `i` is each element from the Vec as they are being iterated. - Can you try multiplying this? -Hint 2: Check the suggestion from the compiler error ;) +Hint 1: `i` 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 +number that way. + +After you've completed both functions, decide for yourself which approach you like +better. What do you think is the more commonly used pattern under Rust developers? """ # MOVE SEMANTICS From 2f7fd513041c7c6275552650881a79b9120aaacf Mon Sep 17 00:00:00 2001 From: mokou Date: Tue, 12 Jul 2022 15:16:25 +0200 Subject: [PATCH 17/71] feat: move vec exercises into their own folder --- exercises/collections/README.md | 24 +++++-------------- exercises/vecs/README.md | 15 ++++++++++++ .../{collections/vec1.rs => vecs/vecs1.rs} | 4 ++-- .../{collections/vec2.rs => vecs/vecs2.rs} | 4 ++-- info.toml | 8 +++---- 5 files changed, 29 insertions(+), 26 deletions(-) create mode 100644 exercises/vecs/README.md rename exercises/{collections/vec1.rs => vecs/vecs1.rs} (84%) rename exercises/{collections/vec2.rs => vecs/vecs2.rs} (92%) diff --git a/exercises/collections/README.md b/exercises/collections/README.md index b6d62acb..30471cf9 100644 --- a/exercises/collections/README.md +++ b/exercises/collections/README.md @@ -1,23 +1,11 @@ -# Collections +# Hashmaps +A *hash map* allows you to associate a value with a particular key. +You may also know this by the names [*unordered map* in C++](https://en.cppreference.com/w/cpp/container/unordered_map), +[*dictionary* in Python](https://docs.python.org/3/tutorial/datastructures.html#dictionaries) or an *associative array* in other languages. -Rust’s standard library includes a number of very useful data -structures called collections. Most other data types represent one -specific value, but collections can contain multiple values. Unlike -the built-in array and tuple types, the data these collections point -to is stored on the heap, which means the amount of data does not need -to be known at compile time and can grow or shrink as the program -runs. - -This exercise will get you familiar with two fundamental data -structures that are used very often in Rust programs: - -* A *vector* allows you to store a variable number of values next to - each other. -* A *hash map* allows you to associate a value with a particular key. - You may also know this by the names [*unordered map* in C++](https://en.cppreference.com/w/cpp/container/unordered_map), - [*dictionary* in Python](https://docs.python.org/3/tutorial/datastructures.html#dictionaries) or an *associative array* in other languages. +This is the other data structure that we've been talking about before, when +talking about Vecs. ## Further information -- [Storing Lists of Values with Vectors](https://doc.rust-lang.org/stable/book/ch08-01-vectors.html) - [Storing Keys with Associated Values in Hash Maps](https://doc.rust-lang.org/book/ch08-03-hash-maps.html) diff --git a/exercises/vecs/README.md b/exercises/vecs/README.md new file mode 100644 index 00000000..ebe90bf3 --- /dev/null +++ b/exercises/vecs/README.md @@ -0,0 +1,15 @@ +# Vectors + +Vectors are one of the most-used Rust data structures. In other programming +languages, they'd simply be called Arrays, but since Rust operates on a +bit of a lower level, an array in Rust is stored on the stack (meaning it +can't grow or shrink, and the size needs to be known at compile time), +and a Vector is stored in the heap (where these restrictions do not apply). + +Vectors are a bit of a later chapter in the book, but we think that they're +useful enough to talk about them a bit earlier. We shall be talking about +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) diff --git a/exercises/collections/vec1.rs b/exercises/vecs/vecs1.rs similarity index 84% rename from exercises/collections/vec1.rs rename to exercises/vecs/vecs1.rs index c26f5691..4e8c4cbb 100644 --- a/exercises/collections/vec1.rs +++ b/exercises/vecs/vecs1.rs @@ -1,8 +1,8 @@ -// vec1.rs +// vecs1.rs // Your task is to create a `Vec` which holds the exact same elements // as in the array `a`. // Make me compile and pass the test! -// Execute `rustlings hint vec1` or use the `hint` watch subcommand for a hint. +// Execute `rustlings hint vecs1` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/exercises/collections/vec2.rs b/exercises/vecs/vecs2.rs similarity index 92% rename from exercises/collections/vec2.rs rename to exercises/vecs/vecs2.rs index db37d1d6..5bea09a2 100644 --- a/exercises/collections/vec2.rs +++ b/exercises/vecs/vecs2.rs @@ -1,10 +1,10 @@ -// vec2.rs +// vecs2.rs // A Vec of even numbers is given. Your task is to complete the loop // so that each number in the Vec is multiplied by 2. // // Make me pass the test! // -// Execute `rustlings hint vec2` or use the `hint` watch subcommand for a hint. +// Execute `rustlings hint vecs2` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/info.toml b/info.toml index af4861c2..1e941e13 100644 --- a/info.toml +++ b/info.toml @@ -242,8 +242,8 @@ Now you have another tool in your toolbox!""" # VECS [[exercises]] -name = "vec1" -path = "exercises/collections/vec1.rs" +name = "vecs1" +path = "exercises/vecs/vecs1.rs" mode = "test" hint = """ In Rust, there are two ways to define a Vector. @@ -256,8 +256,8 @@ of the Rust book to learn more. """ [[exercises]] -name = "vec2" -path = "exercises/collections/vec2.rs" +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 From 3c4c9c54c98142f114018bbbe4d0d96d63646a5b Mon Sep 17 00:00:00 2001 From: mokou Date: Tue, 12 Jul 2022 15:18:05 +0200 Subject: [PATCH 18/71] feat: remove collections to hashmaps --- exercises/{collections => hashmaps}/README.md | 0 .../{collections/hashmap1.rs => hashmaps/hashmaps1.rs} | 4 ++-- .../{collections/hashmap2.rs => hashmaps/hashmaps2.rs} | 4 ++-- info.toml | 10 +++++----- 4 files changed, 9 insertions(+), 9 deletions(-) rename exercises/{collections => hashmaps}/README.md (100%) rename exercises/{collections/hashmap1.rs => hashmaps/hashmaps1.rs} (93%) rename exercises/{collections/hashmap2.rs => hashmaps/hashmaps2.rs} (96%) diff --git a/exercises/collections/README.md b/exercises/hashmaps/README.md similarity index 100% rename from exercises/collections/README.md rename to exercises/hashmaps/README.md diff --git a/exercises/collections/hashmap1.rs b/exercises/hashmaps/hashmaps1.rs similarity index 93% rename from exercises/collections/hashmap1.rs rename to exercises/hashmaps/hashmaps1.rs index 64b5a7f3..26178b0d 100644 --- a/exercises/collections/hashmap1.rs +++ b/exercises/hashmaps/hashmaps1.rs @@ -1,4 +1,4 @@ -// hashmap1.rs +// hashmaps1.rs // A basket of fruits in the form of a hash map needs to be defined. // The key represents the name of the fruit and the value represents // how many of that particular fruit is in the basket. You have to put @@ -8,7 +8,7 @@ // // Make me compile and pass the tests! // -// Execute the command `rustlings hint hashmap1` if you need +// Execute the command `rustlings hint hashmaps1` if you need // hints. // I AM NOT DONE diff --git a/exercises/collections/hashmap2.rs b/exercises/hashmaps/hashmaps2.rs similarity index 96% rename from exercises/collections/hashmap2.rs rename to exercises/hashmaps/hashmaps2.rs index 0abe19ab..1afb8303 100644 --- a/exercises/collections/hashmap2.rs +++ b/exercises/hashmaps/hashmaps2.rs @@ -1,4 +1,4 @@ -// hashmap2.rs +// hashmaps2.rs // A basket of fruits in the form of a hash map is given. The key // represents the name of the fruit and the value represents how many @@ -9,7 +9,7 @@ // // Make me pass the tests! // -// Execute the command `rustlings hint hashmap2` if you need +// Execute the command `rustlings hint hashmaps2` if you need // hints. // I AM NOT DONE diff --git a/info.toml b/info.toml index 1e941e13..c6231203 100644 --- a/info.toml +++ b/info.toml @@ -445,11 +445,11 @@ UNIX_EPOCH and SystemTime are declared in the std::time module. Add a use statem for these two to bring them into scope. You can use nested paths or the glob operator to bring these two in using only one line.""" -# COLLECTIONS +# HASHMAPS [[exercises]] -name = "hashmap1" -path = "exercises/collections/hashmap1.rs" +name = "hashmaps1" +path = "exercises/hashmaps/hashmaps1.rs" mode = "test" hint = """ Hint 1: Take a look at the return type of the function to figure out @@ -459,8 +459,8 @@ Hint 2: Number of fruits should be at least 5. And you have to put """ [[exercises]] -name = "hashmap2" -path = "exercises/collections/hashmap2.rs" +name = "hashmaps2" +path = "exercises/hashmaps/hashmaps2.rs" mode = "test" hint = """ Use the `entry()` and `or_insert()` methods of `HashMap` to achieve this. From 7452d0d60395a9b0247abb3b307ab3437c1f8622 Mon Sep 17 00:00:00 2001 From: mokou Date: Tue, 12 Jul 2022 15:22:01 +0200 Subject: [PATCH 19/71] fix(primitive_types): clean up --- exercises/primitive_types/primitive_types1.rs | 1 - exercises/primitive_types/primitive_types6.rs | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/exercises/primitive_types/primitive_types1.rs b/exercises/primitive_types/primitive_types1.rs index de0d08a6..09121392 100644 --- a/exercises/primitive_types/primitive_types1.rs +++ b/exercises/primitive_types/primitive_types1.rs @@ -4,7 +4,6 @@ // I AM NOT DONE -#[test] fn main() { // Booleans (`bool`) diff --git a/exercises/primitive_types/primitive_types6.rs b/exercises/primitive_types/primitive_types6.rs index b8c9b82b..ddf8b423 100644 --- a/exercises/primitive_types/primitive_types6.rs +++ b/exercises/primitive_types/primitive_types6.rs @@ -1,7 +1,7 @@ // primitive_types6.rs // Use a tuple index to access the second element of `numbers`. // You can put the expression for the second element where ??? is so that the test passes. -// Execute `rustlings hint primitive_types6` for hints! +// Execute `rustlings hint primitive_types6` or use the `hint` watch subcommand for a hint. // I AM NOT DONE From bb0cf92b8b6f0a9db4be92ff5ffc4c507f2847ba Mon Sep 17 00:00:00 2001 From: mokou Date: Tue, 12 Jul 2022 15:25:31 +0200 Subject: [PATCH 20/71] feat(move_semantics): clarify some hints --- exercises/move_semantics/move_semantics1.rs | 2 +- exercises/move_semantics/move_semantics2.rs | 2 +- info.toml | 15 +++++++++------ 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/exercises/move_semantics/move_semantics1.rs b/exercises/move_semantics/move_semantics1.rs index e2f5876d..aac6dfc3 100644 --- a/exercises/move_semantics/move_semantics1.rs +++ b/exercises/move_semantics/move_semantics1.rs @@ -1,5 +1,5 @@ // move_semantics1.rs -// Make me compile! Execute `rustlings hint move_semantics1` for hints :) +// Execute `rustlings hint move_semantics1` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/exercises/move_semantics/move_semantics2.rs b/exercises/move_semantics/move_semantics2.rs index 888dc529..64870850 100644 --- a/exercises/move_semantics/move_semantics2.rs +++ b/exercises/move_semantics/move_semantics2.rs @@ -1,6 +1,6 @@ // move_semantics2.rs // Make me compile without changing line 13 or moving line 10! -// Execute `rustlings hint move_semantics2` for hints :) +// Execute `rustlings hint move_semantics2` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/info.toml b/info.toml index c6231203..a7c46eb6 100644 --- a/info.toml +++ b/info.toml @@ -280,18 +280,21 @@ mode = "compile" hint = """ So you've got the "cannot borrow immutable local variable `vec1` as mutable" error on line 13, right? The fix for this is going to be adding one keyword, and the addition is NOT on line 13 -where the error is.""" +where the error is. + +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" hint = """ -So `vec0` is being *moved* into the function `fill_vec` when we call it on -line 10, which means it gets dropped at the end of `fill_vec`, which means we -can't use `vec0` again on line 13 (or anywhere else in `main` after the -`fill_vec` call for that matter). We could fix this in a few ways, try them -all! +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 to `fill_vec` instead. 2. Make `fill_vec` borrow its argument instead of taking ownership of it, From 16ff57bbffe0ab86d9ef880d45486d6625cc9223 Mon Sep 17 00:00:00 2001 From: exdx Date: Tue, 12 Jul 2022 15:26:55 +0200 Subject: [PATCH 21/71] fix(move_semantics2): clarify referencing --- info.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/info.toml b/info.toml index a7c46eb6..899d4c18 100644 --- a/info.toml +++ b/info.toml @@ -300,7 +300,7 @@ There's a few ways to fix this, try them all if you want: 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 its argument (which will need to be +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!`""" From 2e62505143a726c610a60cc8f11fbb4b0449ba8f Mon Sep 17 00:00:00 2001 From: mokou Date: Tue, 12 Jul 2022 15:43:26 +0200 Subject: [PATCH 22/71] feat(move_semantics): finish updating comments --- exercises/move_semantics/move_semantics3.rs | 2 +- exercises/move_semantics/move_semantics4.rs | 8 ++++---- exercises/move_semantics/move_semantics5.rs | 2 +- exercises/move_semantics/move_semantics6.rs | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/exercises/move_semantics/move_semantics3.rs b/exercises/move_semantics/move_semantics3.rs index 43fef74f..eaa30e33 100644 --- a/exercises/move_semantics/move_semantics3.rs +++ b/exercises/move_semantics/move_semantics3.rs @@ -1,7 +1,7 @@ // move_semantics3.rs // Make me compile without adding new lines-- just changing existing lines! // (no lines with multiple semicolons necessary!) -// Execute `rustlings hint move_semantics3` for hints :) +// Execute `rustlings hint move_semantics3` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/exercises/move_semantics/move_semantics4.rs b/exercises/move_semantics/move_semantics4.rs index 2a23c710..99834ec3 100644 --- a/exercises/move_semantics/move_semantics4.rs +++ b/exercises/move_semantics/move_semantics4.rs @@ -1,8 +1,8 @@ // move_semantics4.rs -// Refactor this code so that instead of having `vec0` and creating the vector -// in `fn main`, we create it within `fn fill_vec` and transfer the -// freshly created vector from fill_vec to its caller. -// Execute `rustlings hint move_semantics4` for hints! +// Refactor this code so that instead of passing `vec0` into the `fill_vec` function, +// the Vector gets created in the function itself and passed back to the main +// function. +// Execute `rustlings hint move_semantics4` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/exercises/move_semantics/move_semantics5.rs b/exercises/move_semantics/move_semantics5.rs index c4704f9e..36eae127 100644 --- a/exercises/move_semantics/move_semantics5.rs +++ b/exercises/move_semantics/move_semantics5.rs @@ -1,7 +1,7 @@ // move_semantics5.rs // Make me compile only by reordering the lines in `main()`, but without // adding, changing or removing any of them. -// Execute `rustlings hint move_semantics5` for hints :) +// Execute `rustlings hint move_semantics5` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/exercises/move_semantics/move_semantics6.rs b/exercises/move_semantics/move_semantics6.rs index 457e7ae7..eb52a848 100644 --- a/exercises/move_semantics/move_semantics6.rs +++ b/exercises/move_semantics/move_semantics6.rs @@ -1,6 +1,6 @@ // move_semantics6.rs -// Make me compile! `rustlings hint move_semantics6` for hints -// You can't change anything except adding or removing references +// Execute `rustlings hint move_semantics6` or use the `hint` watch subcommand for a hint. +// You can't change anything except adding or removing references. // I AM NOT DONE From 19bec503998c3c5618254015bada63b44a713f0e Mon Sep 17 00:00:00 2001 From: mokou Date: Thu, 14 Jul 2022 11:59:29 +0200 Subject: [PATCH 23/71] feat(structs1): convert structs to use i32 types --- exercises/structs/structs1.rs | 11 +++++++---- info.toml | 1 - 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/exercises/structs/structs1.rs b/exercises/structs/structs1.rs index 6d0b2f49..1632b685 100644 --- a/exercises/structs/structs1.rs +++ b/exercises/structs/structs1.rs @@ -1,5 +1,6 @@ // structs1.rs // Address all the TODOs to make the tests pass! +// Execute `rustlings hint structs1` or use the `hint` watch subcommand for a hint. // I AM NOT DONE @@ -21,8 +22,9 @@ mod tests { // TODO: Instantiate a classic c struct! // let green = - assert_eq!(green.name, "green"); - assert_eq!(green.hex, "#00FF00"); + assert_eq!(green.red, 0); + assert_eq!(green.green, 255); + assert_eq!(green.blue, 0); } #[test] @@ -30,8 +32,9 @@ mod tests { // TODO: Instantiate a tuple struct! // let green = - assert_eq!(green.0, "green"); - assert_eq!(green.1, "#00FF00"); + assert_eq!(green.0, 0); + assert_eq!(green.1, 255); + assert_eq!(green.2, 0); } #[test] diff --git a/info.toml b/info.toml index 899d4c18..2dc49a38 100644 --- a/info.toml +++ b/info.toml @@ -357,7 +357,6 @@ Can you figure out how? Another hint: it has to do with the `&` character.""" - # STRUCTS [[exercises]] From 4dffa0d10df61748b0098ad4428848e6f3e90bff Mon Sep 17 00:00:00 2001 From: mokou Date: Thu, 14 Jul 2022 12:00:46 +0200 Subject: [PATCH 24/71] fix(structs1): rename to unit-like struct --- exercises/structs/structs1.rs | 10 +++++----- info.toml | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/exercises/structs/structs1.rs b/exercises/structs/structs1.rs index 1632b685..0d91c469 100644 --- a/exercises/structs/structs1.rs +++ b/exercises/structs/structs1.rs @@ -11,7 +11,7 @@ struct ColorClassicStruct { struct ColorTupleStruct(/* TODO: Something goes here */); #[derive(Debug)] -struct UnitStruct; +struct UnitLikeStruct; #[cfg(test)] mod tests { @@ -39,10 +39,10 @@ mod tests { #[test] fn unit_structs() { - // TODO: Instantiate a unit struct! - // let unit_struct = - let message = format!("{:?}s are fun!", unit_struct); + // TODO: Instantiate a unit-like struct! + // let unit_like_struct = + let message = format!("{:?}s are fun!", unit_like_struct); - assert_eq!(message, "UnitStructs are fun!"); + assert_eq!(message, "UnitLikeStructs are fun!"); } } diff --git a/info.toml b/info.toml index 2dc49a38..357a25c6 100644 --- a/info.toml +++ b/info.toml @@ -367,7 +367,7 @@ hint = """ Rust has more than one type of struct. Three actually, all variants are used to package related data together. There are normal (or classic) structs. These are named collections of related data stored in fields. Tuple structs are basically just named tuples. -Finally, Unit structs. These don't have any fields and are useful for generics. +Finally, Unit-like structs. These don't have any fields and are useful for generics. In this exercise you need to complete and implement one of each kind. Read more about structs in The Book: https://doc.rust-lang.org/book/ch05-01-defining-structs.html""" From 4531c21bf1b54ff5fa8cc796584043b826cf78e8 Mon Sep 17 00:00:00 2001 From: camperdue42 Date: Fri, 31 Dec 2021 01:05:34 -0500 Subject: [PATCH 25/71] fix(structs3): Add panic! statement into structs3 closes #685 --- exercises/structs/structs3.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exercises/structs/structs3.rs b/exercises/structs/structs3.rs index e84f2ebc..e5666e21 100644 --- a/exercises/structs/structs3.rs +++ b/exercises/structs/structs3.rs @@ -16,7 +16,7 @@ struct Package { impl Package { fn new(sender_country: String, recipient_country: String, weight_in_grams: i32) -> Package { if weight_in_grams <= 0 { - // panic statement goes here... + panic!("Can not ship a weightless package.") } else { Package { sender_country, From 886d599c96ad0725cee05c50cf4ea9718fc02746 Mon Sep 17 00:00:00 2001 From: mokou Date: Thu, 14 Jul 2022 12:04:54 +0200 Subject: [PATCH 26/71] fix(structs): add hint comments --- exercises/structs/structs2.rs | 1 + exercises/structs/structs3.rs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/exercises/structs/structs2.rs b/exercises/structs/structs2.rs index f9c6427d..32e311fa 100644 --- a/exercises/structs/structs2.rs +++ b/exercises/structs/structs2.rs @@ -1,5 +1,6 @@ // structs2.rs // Address all the TODOs to make the tests pass! +// Execute `rustlings hint structs2` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/exercises/structs/structs3.rs b/exercises/structs/structs3.rs index e5666e21..0b3615f4 100644 --- a/exercises/structs/structs3.rs +++ b/exercises/structs/structs3.rs @@ -2,7 +2,7 @@ // Structs contain data, but can also have logic. In this exercise we have // defined the Package struct and we want to test some logic attached to it. // Make the code compile and the tests pass! -// If you have issues execute `rustlings hint structs3` +// Execute `rustlings hint structs3` or use the `hint` watch subcommand for a hint. // I AM NOT DONE From d0e8efd19ee9a4a7fe9a62ee76bc035371321c09 Mon Sep 17 00:00:00 2001 From: Ryosuke YASUOKA Date: Sun, 9 Jan 2022 19:30:31 +0900 Subject: [PATCH 27/71] feat(enums3): Add hint --- info.toml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/info.toml b/info.toml index 357a25c6..dc176ed0 100644 --- a/info.toml +++ b/info.toml @@ -415,7 +415,11 @@ such as no data, anonymous structs, a single string, tuples, ...etc""" name = "enums3" path = "exercises/enums/enums3.rs" mode = "test" -hint = "No hints this time ;)" +hint = """ +As a first step, you can define enums to compile this code without errors. +and then create a match expression in `process()`. +Note that you need to deconstruct some message variants +in the match expression to get value in the variant.""" # MODULES From c6bc97adc10aecbf6a1ba5ff5c7beda1f421a098 Mon Sep 17 00:00:00 2001 From: mokou Date: Thu, 14 Jul 2022 12:11:38 +0200 Subject: [PATCH 28/71] feat(enums3): add hint comment, remove enums1 hint --- exercises/enums/enums1.rs | 2 +- exercises/enums/enums2.rs | 2 +- exercises/enums/enums3.rs | 1 + info.toml | 3 +-- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/exercises/enums/enums1.rs b/exercises/enums/enums1.rs index a2223d33..511ba740 100644 --- a/exercises/enums/enums1.rs +++ b/exercises/enums/enums1.rs @@ -1,5 +1,5 @@ // enums1.rs -// Make me compile! Execute `rustlings hint enums1` for hints! +// No hints this time! ;) // I AM NOT DONE diff --git a/exercises/enums/enums2.rs b/exercises/enums/enums2.rs index ec32d952..18479f87 100644 --- a/exercises/enums/enums2.rs +++ b/exercises/enums/enums2.rs @@ -1,5 +1,5 @@ // enums2.rs -// Make me compile! Execute `rustlings hint enums2` for hints! +// Execute `rustlings hint enums2` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/exercises/enums/enums3.rs b/exercises/enums/enums3.rs index 178b40c4..55acf6bc 100644 --- a/exercises/enums/enums3.rs +++ b/exercises/enums/enums3.rs @@ -1,5 +1,6 @@ // enums3.rs // Address all the TODOs to make the tests pass! +// Execute `rustlings hint enums3` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/info.toml b/info.toml index dc176ed0..b1e448c9 100644 --- a/info.toml +++ b/info.toml @@ -400,8 +400,7 @@ Have a look in The Book, to find out more about method implementations: https:// name = "enums1" path = "exercises/enums/enums1.rs" mode = "compile" -hint = """ -The declaration of the enumeration type has not been defined yet.""" +hint = "No hints this time ;)" [[exercises]] name = "enums2" From f5e4c16eed0c9e86398284bb6732981c3cc074c8 Mon Sep 17 00:00:00 2001 From: mokou Date: Thu, 14 Jul 2022 12:18:21 +0200 Subject: [PATCH 29/71] feat(strings): move before modules --- exercises/strings/strings1.rs | 2 +- exercises/strings/strings2.rs | 2 +- info.toml | 46 +++++++++++++++++------------------ 3 files changed, 25 insertions(+), 25 deletions(-) diff --git a/exercises/strings/strings1.rs b/exercises/strings/strings1.rs index 80902444..0de86a1d 100644 --- a/exercises/strings/strings1.rs +++ b/exercises/strings/strings1.rs @@ -1,6 +1,6 @@ // strings1.rs // Make me compile without changing the function signature! -// Execute `rustlings hint strings1` for hints ;) +// Execute `rustlings hint strings1` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/exercises/strings/strings2.rs b/exercises/strings/strings2.rs index 5a2ce74a..0c48ec95 100644 --- a/exercises/strings/strings2.rs +++ b/exercises/strings/strings2.rs @@ -1,6 +1,6 @@ // strings2.rs // Make me compile without changing the function signature! -// Execute `rustlings hint strings2` for hints :) +// Execute `rustlings hint strings2` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/info.toml b/info.toml index b1e448c9..8174fc8f 100644 --- a/info.toml +++ b/info.toml @@ -420,6 +420,29 @@ and then create a match expression in `process()`. Note that you need to deconstruct some message variants in the match expression to get value in the variant.""" +# STRINGS + +[[exercises]] +name = "strings1" +path = "exercises/strings/strings1.rs" +mode = "compile" +hint = """ +The `current_favorite_color` function is currently returning a string slice with the `'static` +lifetime. We know this because the data of the string lives in our code itself -- it doesn't +come from a file or user input or another program -- so it will live as long as our program +lives. But it is still a string slice. There's one way to create a `String` by converting a +string slice covered in the Strings chapter of the book, and another way that uses the `From` +trait.""" + +[[exercises]] +name = "strings2" +path = "exercises/strings/strings2.rs" +mode = "compile" +hint = """ +Yes, it would be really easy to fix this by just changing the value bound to `word` to be a +string slice instead of a `String`, wouldn't it?? There is a way to add one character to line +9, though, that will coerce the `String` into a string slice.""" + # MODULES [[exercises]] @@ -472,29 +495,6 @@ Use the `entry()` and `or_insert()` methods of `HashMap` to achieve this. Learn more at https://doc.rust-lang.org/stable/book/ch08-03-hash-maps.html#only-inserting-a-value-if-the-key-has-no-value """ -# STRINGS - -[[exercises]] -name = "strings1" -path = "exercises/strings/strings1.rs" -mode = "compile" -hint = """ -The `current_favorite_color` function is currently returning a string slice with the `'static` -lifetime. We know this because the data of the string lives in our code itself -- it doesn't -come from a file or user input or another program -- so it will live as long as our program -lives. But it is still a string slice. There's one way to create a `String` by converting a -string slice covered in the Strings chapter of the book, and another way that uses the `From` -trait.""" - -[[exercises]] -name = "strings2" -path = "exercises/strings/strings2.rs" -mode = "compile" -hint = """ -Yes, it would be really easy to fix this by just changing the value bound to `word` to be a -string slice instead of a `String`, wouldn't it?? There is a way to add one character to line -9, though, that will coerce the `String` into a string slice.""" - # TEST 2 [[exercises]] From c1ed6b10fe0725846fef8328b328159b6302fe3b Mon Sep 17 00:00:00 2001 From: mokou Date: Thu, 14 Jul 2022 12:31:28 +0200 Subject: [PATCH 30/71] feat(strings): add strings3 --- exercises/strings/strings3.rs | 41 +++++++++++++++++++++++++++++++++++ info.toml | 11 ++++++++++ 2 files changed, 52 insertions(+) create mode 100644 exercises/strings/strings3.rs diff --git a/exercises/strings/strings3.rs b/exercises/strings/strings3.rs new file mode 100644 index 00000000..bb0a259e --- /dev/null +++ b/exercises/strings/strings3.rs @@ -0,0 +1,41 @@ +// strings3.rs +// Execute `rustlings hint strings3` or use the `hint` watch subcommand for a hint. + +fn trim_me(input: &str) -> String { + // TODO: Remove whitespace from the end of a string! + ??? +} + +fn compose_me(input: &str) -> String { + // TODO: Add " world!" to the string! There's multiple ways to do this! + ??? +} + +fn replace_me(input: &str) -> String { + // TODO: Replace "cars" in the string with "balloons"! + ??? +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn trim_a_string() { + assert_eq!(trim_me("Hello! "), "Hello!"); + assert_eq!(trim_me(" What's up!"), "What's up!"); + assert_eq!(trim_me(" Hola! "), "Hola!"); + } + + #[test] + fn compose_a_string() { + assert_eq!(compose_me("Hello"), "Hello world!"); + assert_eq!(compose_me("Goodbye"), "Goodbye world!"); + } + + #[test] + fn replace_a_string() { + assert_eq!(replace_me("I think cars are cool"), "I think balloons are cool"); + assert_eq!(replace_me("I love to look at cars"), "I love to look at balloons"); + } +} diff --git a/info.toml b/info.toml index 8174fc8f..c54672b3 100644 --- a/info.toml +++ b/info.toml @@ -443,6 +443,17 @@ Yes, it would be really easy to fix this by just changing the value bound to `wo string slice instead of a `String`, wouldn't it?? There is a way to add one character to line 9, though, that will coerce the `String` into a string slice.""" +[[exercises]] +name = "strings3" +path = "exercises/strings/strings3.rs" +mode = "test" +hint = """ +There's tons of useful standard library functions for strings. Let's try and use some of +them! + +For the compose_me method: You can either use the `format!` macro, or convert the string +slice into an owned string, which you can then freely extend.""" + # MODULES [[exercises]] From fe54d0f85b3170ba950bab8be9756c9dbf0098fd Mon Sep 17 00:00:00 2001 From: mokou Date: Thu, 14 Jul 2022 12:35:49 +0200 Subject: [PATCH 31/71] fix(modules): adjust hint comments --- exercises/modules/modules1.rs | 2 +- exercises/modules/modules2.rs | 3 +-- exercises/modules/modules3.rs | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/exercises/modules/modules1.rs b/exercises/modules/modules1.rs index 1a2bd0dd..8dd0e402 100644 --- a/exercises/modules/modules1.rs +++ b/exercises/modules/modules1.rs @@ -1,5 +1,5 @@ // modules1.rs -// Make me compile! Execute `rustlings hint modules1` for hints :) +// Execute `rustlings hint modules1` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/exercises/modules/modules2.rs b/exercises/modules/modules2.rs index 87f0c458..c30a3897 100644 --- a/exercises/modules/modules2.rs +++ b/exercises/modules/modules2.rs @@ -1,12 +1,11 @@ // modules2.rs // You can bring module paths into scopes and provide new names for them with the // 'use' and 'as' keywords. Fix these 'use' statements to make the code compile. -// Make me compile! Execute `rustlings hint modules2` for hints :) +// Execute `rustlings hint modules2` or use the `hint` watch subcommand for a hint. // I AM NOT DONE mod delicious_snacks { - // TODO: Fix these use statements use self::fruits::PEAR as ??? use self::veggies::CUCUMBER as ??? diff --git a/exercises/modules/modules3.rs b/exercises/modules/modules3.rs index 8eed77df..35e07990 100644 --- a/exercises/modules/modules3.rs +++ b/exercises/modules/modules3.rs @@ -3,7 +3,7 @@ // and especially from the Rust standard library into your scope. // Bring SystemTime and UNIX_EPOCH // from the std::time module. Bonus style points if you can do it with one line! -// Make me compile! Execute `rustlings hint modules3` for hints :) +// Execute `rustlings hint modules3` or use the `hint` watch subcommand for a hint. // I AM NOT DONE From 1e54bc61e81a81b0647325f724690b376de50a2a Mon Sep 17 00:00:00 2001 From: Sateesh Basavaraju Date: Fri, 4 Jun 2021 16:09:12 +0530 Subject: [PATCH 32/71] feat: Add hashmap3 exercise. --- exercises/hashmaps/hashmaps3.rs | 88 +++++++++++++++++++++++++++++++++ info.toml | 12 +++++ 2 files changed, 100 insertions(+) create mode 100644 exercises/hashmaps/hashmaps3.rs diff --git a/exercises/hashmaps/hashmaps3.rs b/exercises/hashmaps/hashmaps3.rs new file mode 100644 index 00000000..60293f2e --- /dev/null +++ b/exercises/hashmaps/hashmaps3.rs @@ -0,0 +1,88 @@ +// hashmaps3.rs + +// A list of scores (one per line) of a soccer match is given. Each line +// is of the form : +// ,,, +// Example: England,France,4,2 (England scored 4 goals, France 2). + +// You have to build a scores table containing the name of the team, goals +// the team scored, and goals the team conceded. One approach to build +// the scores table is to use a Hashmap. The solution is partially +// written to use a Hashmap, complete it to pass the test. + +// Make me pass the tests! + +// Execute the command `rustlings hint hashmap3` if you need +// hints. + +// I AM NOT DONE + +use std::collections::HashMap; + +// A structure to store team name and its goal details. +struct Team { + name: String, + goals_scored: u8, + goals_conceded: u8, +} + +fn build_scores_table(results: String) -> HashMap { + // The name of the team is the key and its associated struct is the value. + let mut scores: HashMap = HashMap::new(); + + for r in results.lines() { + let v: Vec<&str> = r.split(',').collect(); + let team_1_name = v[0].to_string(); + let team_1_score: u8 = v[2].parse().unwrap(); + let team_2_name = v[1].to_string(); + let team_2_score: u8 = v[3].parse().unwrap(); + // TODO: Populate the scores table with details extracted from the + // current line. Keep in mind that goals scored by team_1 + // will be number of goals conceded from team_2, and similarly + // goals scored by team_2 will be the number of goals conceded by + // team_1. + } + scores +} + +#[cfg(test)] +mod tests { + use super::*; + + fn get_results() -> String { + let results = "".to_string() + + "England,France,4,2\n" + + "France,Italy,3,1\n" + + "Poland,Spain,2,0\n" + + "Germany,England,2,1\n"; + results + } + + #[test] + fn build_scores() { + let scores = build_scores_table(get_results()); + + let mut keys: Vec<&String> = scores.keys().collect(); + keys.sort(); + assert_eq!( + keys, + vec!["England", "France", "Germany", "Italy", "Poland", "Spain"] + ); + } + + #[test] + fn validate_team_score_1() { + let scores = build_scores_table(get_results()); + let team = scores.get("England").unwrap(); + assert_eq!(team.goals_scored, 5); + assert_eq!(team.goals_conceded, 4); + } + + #[test] + fn validate_team_score_2() { + let scores = build_scores_table(get_results()); + let team = scores.get("Spain").unwrap(); + assert_eq!(team.goals_scored, 0); + assert_eq!(team.goals_conceded, 2); + } +} diff --git a/info.toml b/info.toml index c54672b3..ec2d8172 100644 --- a/info.toml +++ b/info.toml @@ -506,6 +506,18 @@ Use the `entry()` and `or_insert()` methods of `HashMap` to achieve this. Learn more at https://doc.rust-lang.org/stable/book/ch08-03-hash-maps.html#only-inserting-a-value-if-the-key-has-no-value """ +[[exercises]] +name = "hashmaps3" +path = "exercises/hashmaps/hashmaps3.rs" +mode = "test" +hint = """ +Hint 1: Use the `entry()` and `or_insert()` methods of `HashMap` to insert entries corresponding to each team in the scores table. +Learn more at https://doc.rust-lang.org/stable/book/ch08-03-hash-maps.html#only-inserting-a-value-if-the-key-has-no-value +Hint 2: If there is already an entry for a given key, the value returned by `entry()` can be updated based on the existing value. +Learn more at https://doc.rust-lang.org/book/ch08-03-hash-maps.html#updating-a-value-based-on-the-old-value +""" + + # TEST 2 [[exercises]] From ab8572e15bf6765471490281ba2a1c8f88275e40 Mon Sep 17 00:00:00 2001 From: mokou Date: Thu, 14 Jul 2022 12:58:28 +0200 Subject: [PATCH 33/71] fix(hashmaps): adjust hint comments --- exercises/hashmaps/hashmaps1.rs | 3 +-- exercises/hashmaps/hashmaps2.rs | 3 +-- exercises/hashmaps/hashmaps3.rs | 3 +-- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/exercises/hashmaps/hashmaps1.rs b/exercises/hashmaps/hashmaps1.rs index 26178b0d..fd8dd2f8 100644 --- a/exercises/hashmaps/hashmaps1.rs +++ b/exercises/hashmaps/hashmaps1.rs @@ -8,8 +8,7 @@ // // Make me compile and pass the tests! // -// Execute the command `rustlings hint hashmaps1` if you need -// hints. +// Execute `rustlings hint hashmaps1` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/exercises/hashmaps/hashmaps2.rs b/exercises/hashmaps/hashmaps2.rs index 1afb8303..454b3e1d 100644 --- a/exercises/hashmaps/hashmaps2.rs +++ b/exercises/hashmaps/hashmaps2.rs @@ -9,8 +9,7 @@ // // Make me pass the tests! // -// Execute the command `rustlings hint hashmaps2` if you need -// hints. +// Execute `rustlings hint hashmaps2` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/exercises/hashmaps/hashmaps3.rs b/exercises/hashmaps/hashmaps3.rs index 60293f2e..18dd44c9 100644 --- a/exercises/hashmaps/hashmaps3.rs +++ b/exercises/hashmaps/hashmaps3.rs @@ -12,8 +12,7 @@ // Make me pass the tests! -// Execute the command `rustlings hint hashmap3` if you need -// hints. +// Execute `rustlings hint hashmaps3` or use the `hint` watch subcommand for a hint. // I AM NOT DONE From f443f4e7b31467b29271aab477c63eb64aba1be3 Mon Sep 17 00:00:00 2001 From: mokou Date: Thu, 14 Jul 2022 13:01:40 +0200 Subject: [PATCH 34/71] feat: move quiz2 to be strings4 --- exercises/strings/strings4.rs | 29 +++++++++++++++++++++++++++++ info.toml | 11 ++++++++--- 2 files changed, 37 insertions(+), 3 deletions(-) create mode 100644 exercises/strings/strings4.rs diff --git a/exercises/strings/strings4.rs b/exercises/strings/strings4.rs new file mode 100644 index 00000000..c410b562 --- /dev/null +++ b/exercises/strings/strings4.rs @@ -0,0 +1,29 @@ +// strings4.rs + +// Ok, here are a bunch of values-- some are `String`s, some are `&str`s. Your +// task is to call one of these two functions on each value depending on what +// you think each value is. That is, add either `string_slice` or `string` +// before the parentheses on each line. If you're right, it will compile! +// No hints this time! + +// I AM NOT DONE + +fn string_slice(arg: &str) { + println!("{}", arg); +} +fn string(arg: String) { + println!("{}", arg); +} + +fn main() { + ???("blue"); + ???("red".to_string()); + ???(String::from("hi")); + ???("rust is fun!".to_owned()); + ???("nice weather".into()); + ???(format!("Interpolation {}", "Station")); + ???(&String::from("abc")[0..1]); + ???(" hello there ".trim()); + ???("Happy Monday!".to_string().replace("Mon", "Tues")); + ???("mY sHiFt KeY iS sTiCkY".to_lowercase()); +} diff --git a/info.toml b/info.toml index ec2d8172..0f7d9253 100644 --- a/info.toml +++ b/info.toml @@ -167,7 +167,7 @@ For that first compiler error, it's important in Rust that each conditional block returns the same type! To get the tests passing, you will need a couple conditions checking different input values.""" -# TEST 1 +# QUIZ 1 [[exercises]] name = "quiz1" @@ -454,6 +454,12 @@ them! For the compose_me method: You can either use the `format!` macro, or convert the string slice into an owned string, which you can then freely extend.""" +[[exercises]] +name = "strings4" +path = "exercises/strings/strings4.rs" +mode = "compile" +hint = "No hints this time ;)" + # MODULES [[exercises]] @@ -517,8 +523,7 @@ Hint 2: If there is already an entry for a given key, the value returned by `ent Learn more at https://doc.rust-lang.org/book/ch08-03-hash-maps.html#updating-a-value-based-on-the-old-value """ - -# TEST 2 +# QUIZ 2 [[exercises]] name = "quiz2" From c64b340622a59f60b0b056ed849557bc4872a535 Mon Sep 17 00:00:00 2001 From: mokou Date: Thu, 14 Jul 2022 13:16:32 +0200 Subject: [PATCH 35/71] feat: rework quiz2 --- exercises/quiz2.rs | 73 ++++++++++++++++++++++++++++++++-------------- info.toml | 2 +- 2 files changed, 52 insertions(+), 23 deletions(-) diff --git a/exercises/quiz2.rs b/exercises/quiz2.rs index de0dce95..d2211c7c 100644 --- a/exercises/quiz2.rs +++ b/exercises/quiz2.rs @@ -1,30 +1,59 @@ // quiz2.rs // This is a quiz for the following sections: // - Strings +// - Vecs +// - Move semantics +// - Modules +// - Enums -// Ok, here are a bunch of values-- some are `String`s, some are `&str`s. Your -// task is to call one of these two functions on each value depending on what -// you think each value is. That is, add either `string_slice` or `string` -// before the parentheses on each line. If you're right, it will compile! +// Let's build a little machine in form of a function. +// As input, we're going to give a list of strings and commands. These commands +// determine what action is going to be applied to the string. It can either be: +// - Uppercase the string +// - Trim the string +// - Append "bar" to the string a specified amount of times +// The exact form of this will be: +// - The input is going to be a Vector of a 2-length tuple, +// the first element is the string, the second one is the command. +// - The output element is going to be a Vector of strings. -// I AM NOT DONE - -fn string_slice(arg: &str) { - println!("{}", arg); -} -fn string(arg: String) { - println!("{}", arg); +pub enum Command { + Uppercase, + Trim, + Append(usize), } -fn main() { - ???("blue"); - ???("red".to_string()); - ???(String::from("hi")); - ???("rust is fun!".to_owned()); - ???("nice weather".into()); - ???(format!("Interpolation {}", "Station")); - ???(&String::from("abc")[0..1]); - ???(" hello there ".trim()); - ???("Happy Monday!".to_string().replace("Mon", "Tues")); - ???("mY sHiFt KeY iS sTiCkY".to_lowercase()); +mod my_module { + use super::Command; + + // TODO: Complete the function signature! + pub fn transformer(input: ???) -> ??? { + // TODO: Complete the output declaration! + let mut output: ??? = vec![]; + for (string, command) in input.iter() { + // TODO: Complete the function body. You can do it! + } + output + } +} + +#[cfg(test)] +mod tests { + // TODO: What to we have to import to have `transformer` in scope? + use ???; + use super::Command; + + #[test] + fn it_works() { + let output = transformer(vec![ + ("hello".into(), Command::Uppercase), + (" all roads lead to rome! ".into(), Command::Trim), + ("foo".into(), Command::Append(1)), + ("bar".into(), Command::Append(5)), + ]); + assert_eq!(output[0], "HELLO"); + assert_eq!(output[1], "all roads lead to rome!"); + assert_eq!(output[2], "foobar"); + assert_eq!(output[3], "barbarbarbarbarbar"); + } } diff --git a/info.toml b/info.toml index 0f7d9253..0a94f7de 100644 --- a/info.toml +++ b/info.toml @@ -528,7 +528,7 @@ Learn more at https://doc.rust-lang.org/book/ch08-03-hash-maps.html#updating-a-v [[exercises]] name = "quiz2" path = "exercises/quiz2.rs" -mode = "compile" +mode = "test" hint = "No hints this time ;)" # ERROR HANDLING From 472d7944f95e41d8fa9f78ac2870a3827afdc544 Mon Sep 17 00:00:00 2001 From: mokou Date: Thu, 14 Jul 2022 17:30:04 +0200 Subject: [PATCH 36/71] fix(quiz2): add hint comment --- exercises/quiz2.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/exercises/quiz2.rs b/exercises/quiz2.rs index d2211c7c..5d3ccc03 100644 --- a/exercises/quiz2.rs +++ b/exercises/quiz2.rs @@ -16,6 +16,7 @@ // - The input is going to be a Vector of a 2-length tuple, // the first element is the string, the second one is the command. // - The output element is going to be a Vector of strings. +// Execute `rustlings hint quiz2` or use the `hint` watch subcommand for a hint. pub enum Command { Uppercase, From b644558c19dd1f0319204f50c1c162562edb79b1 Mon Sep 17 00:00:00 2001 From: mokou Date: Thu, 14 Jul 2022 17:34:50 +0200 Subject: [PATCH 37/71] fix: rename option to options --- exercises/{option => options}/README.md | 2 +- .../option1.rs => options/options1.rs} | 4 +- .../option2.rs => options/options2.rs} | 2 +- .../option3.rs => options/options3.rs} | 2 +- info.toml | 84 +++++++++---------- 5 files changed, 47 insertions(+), 47 deletions(-) rename exercises/{option => options}/README.md (99%) rename exercises/{option/option1.rs => options/options1.rs} (81%) rename exercises/{option/option2.rs => options/options2.rs} (98%) rename exercises/{option/option3.rs => options/options3.rs} (96%) diff --git a/exercises/option/README.md b/exercises/options/README.md similarity index 99% rename from exercises/option/README.md rename to exercises/options/README.md index 89c00289..6140a167 100644 --- a/exercises/option/README.md +++ b/exercises/options/README.md @@ -1,4 +1,4 @@ -# Option +# Options Type Option represents an optional value: every Option is either Some and contains a value, or None, and does not. Option types are very common in Rust code, as they have a number of uses: diff --git a/exercises/option/option1.rs b/exercises/options/options1.rs similarity index 81% rename from exercises/option/option1.rs rename to exercises/options/options1.rs index 17cf4f60..9d96817b 100644 --- a/exercises/option/option1.rs +++ b/exercises/options/options1.rs @@ -1,5 +1,5 @@ -// option1.rs -// Make me compile! Execute `rustlings hint option1` for hints +// options1.rs +// Execute `rustlings hint options1` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/exercises/option/option2.rs b/exercises/options/options2.rs similarity index 98% rename from exercises/option/option2.rs rename to exercises/options/options2.rs index c6b83ece..a1c21d3e 100644 --- a/exercises/option/option2.rs +++ b/exercises/options/options2.rs @@ -1,4 +1,4 @@ -// option2.rs +// options2.rs // Make me compile! Execute `rustlings hint option2` for hints // I AM NOT DONE diff --git a/exercises/option/option3.rs b/exercises/options/options3.rs similarity index 96% rename from exercises/option/option3.rs rename to exercises/options/options3.rs index 045d2acb..4cba4ad0 100644 --- a/exercises/option/option3.rs +++ b/exercises/options/options3.rs @@ -1,4 +1,4 @@ -// option3.rs +// options3.rs // Make me compile! Execute `rustlings hint option3` for hints // I AM NOT DONE diff --git a/info.toml b/info.toml index 0a94f7de..6bcf2786 100644 --- a/info.toml +++ b/info.toml @@ -531,6 +531,48 @@ path = "exercises/quiz2.rs" mode = "test" hint = "No hints this time ;)" +# OPTIONS + +[[exercises]] +name = "options1" +path = "exercises/options/options1.rs" +mode = "compile" +hint = """ +Hint 1: Check out some functions of Option: +is_some +is_none +unwrap + +and: +pattern matching + +Hint 2: There are no sensible defaults for the value of an Array; the values need to be filled before use. +""" + +[[exercises]] +name = "options2" +path = "exercises/options/options2.rs" +mode = "compile" +hint = """ +check out: +https://doc.rust-lang.org/rust-by-example/flow_control/if_let.html +https://doc.rust-lang.org/rust-by-example/flow_control/while_let.html + +Remember that Options can be stacked in if let and while let. +For example: Some(Some(variable)) = variable2 +Also see Option::flatten +""" + +[[exercises]] +name = "options3" +path = "exercises/options/options3.rs" +mode = "compile" +hint = """ +The compiler says a partial move happened in the `match` +statement. How can this be avoided? The compiler shows the correction +needed. After making the correction as suggested by the compiler, do +read: https://doc.rust-lang.org/std/keyword.ref.html""" + # ERROR HANDLING [[exercises]] @@ -661,48 +703,6 @@ ReportCard struct generic, but also the correct property - you will need to chan of the struct slightly too...you can do it! """ -# OPTIONS - -[[exercises]] -name = "option1" -path = "exercises/option/option1.rs" -mode = "compile" -hint = """ -Hint 1: Check out some functions of Option: -is_some -is_none -unwrap - -and: -pattern matching - -Hint 2: There are no sensible defaults for the value of an Array; the values need to be filled before use. -""" - -[[exercises]] -name = "option2" -path = "exercises/option/option2.rs" -mode = "compile" -hint = """ -check out: -https://doc.rust-lang.org/rust-by-example/flow_control/if_let.html -https://doc.rust-lang.org/rust-by-example/flow_control/while_let.html - -Remember that Options can be stacked in if let and while let. -For example: Some(Some(variable)) = variable2 -Also see Option::flatten -""" - -[[exercises]] -name = "option3" -path = "exercises/option/option3.rs" -mode = "compile" -hint = """ -The compiler says a partial move happened in the `match` -statement. How can this be avoided? The compiler shows the correction -needed. After making the correction as suggested by the compiler, do -read: https://doc.rust-lang.org/std/keyword.ref.html""" - # TRAITS [[exercises]] From 06e4fd376586709082664a304f0394244d4ab6bd Mon Sep 17 00:00:00 2001 From: mokou Date: Thu, 14 Jul 2022 17:53:27 +0200 Subject: [PATCH 38/71] feat(options1): rewrite to remove array stuff --- exercises/options/options1.rs | 32 +++++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/exercises/options/options1.rs b/exercises/options/options1.rs index 9d96817b..038fb48e 100644 --- a/exercises/options/options1.rs +++ b/exercises/options/options1.rs @@ -8,16 +8,30 @@ fn print_number(maybe_number: Option) { println!("printing: {}", maybe_number.unwrap()); } -fn main() { - print_number(13); - print_number(99); +// This function returns how much icecream there is left in the fridge. +// If it's before 10PM, there's 5 pieces left. At 10PM, someone eats them +// all, so there'll be no more left :( +// TODO: Return an Option! +fn maybe_icecream(time_of_day: u16) -> Option { + // We use the 24-hour system here, so 10PM is a value of 22 + ??? +} - let mut numbers: [Option; 5]; - for iter in 0..5 { - let number_to_add: u16 = { - ((iter * 1235) + 2) / (4 * 16) - }; +#[cfg(test)] +mod tests { + use super::*; - numbers[iter as usize] = number_to_add; + #[test] + fn check_icecream() { + assert_eq!(maybe_icecream(10), Some(5)); + assert_eq!(maybe_icecream(23), None); + assert_eq!(maybe_icecream(22), None); + } + + #[test] + fn raw_value() { + // TODO: Fix this test. How do you get at the value contained in the Option? + let icecreams = maybe_icecream(12); + assert_eq!(icecreams, 5); } } From b71feed82464f476611765e8621b32e615b5dddc Mon Sep 17 00:00:00 2001 From: mokou Date: Thu, 14 Jul 2022 17:53:42 +0200 Subject: [PATCH 39/71] feat(options): add hint comments --- exercises/options/options2.rs | 2 +- exercises/options/options3.rs | 2 +- info.toml | 15 ++++----------- 3 files changed, 6 insertions(+), 13 deletions(-) diff --git a/exercises/options/options2.rs b/exercises/options/options2.rs index a1c21d3e..75b66a37 100644 --- a/exercises/options/options2.rs +++ b/exercises/options/options2.rs @@ -1,5 +1,5 @@ // options2.rs -// Make me compile! Execute `rustlings hint option2` for hints +// Execute `rustlings hint options2` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/exercises/options/options3.rs b/exercises/options/options3.rs index 4cba4ad0..3f995c52 100644 --- a/exercises/options/options3.rs +++ b/exercises/options/options3.rs @@ -1,5 +1,5 @@ // options3.rs -// Make me compile! Execute `rustlings hint option3` for hints +// Execute `rustlings hint options3` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/info.toml b/info.toml index 6bcf2786..b13ed45e 100644 --- a/info.toml +++ b/info.toml @@ -536,18 +536,11 @@ hint = "No hints this time ;)" [[exercises]] name = "options1" path = "exercises/options/options1.rs" -mode = "compile" +mode = "test" hint = """ -Hint 1: Check out some functions of Option: -is_some -is_none -unwrap - -and: -pattern matching - -Hint 2: There are no sensible defaults for the value of an Array; the values need to be filled before use. -""" +Options can have a Some value, with an inner value, or a None value, without an inner value. +There's multiple ways to get at the inner value, you can use unwrap, or pattern match. Unwrapping +is the easiest, but how do you do it safely so that it doesn't panic in your face later?""" [[exercises]] name = "options2" From 582320aded8a9369f8b5a959419f04ea6d3f5b04 Mon Sep 17 00:00:00 2001 From: Steven nguyen Date: Tue, 8 Feb 2022 17:46:22 -0600 Subject: [PATCH 40/71] chore(errors1): use `is_empty()` instead of `len() > 0` more idiomatic according to clippy --- exercises/error_handling/errors1.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/exercises/error_handling/errors1.rs b/exercises/error_handling/errors1.rs index c417fb26..1a2a8577 100644 --- a/exercises/error_handling/errors1.rs +++ b/exercises/error_handling/errors1.rs @@ -8,11 +8,11 @@ // I AM NOT DONE pub fn generate_nametag_text(name: String) -> Option { - if name.len() > 0 { - Some(format!("Hi! My name is {}", name)) - } else { + if name.is_empty() { // Empty names aren't allowed. None + } else { + Some(format!("Hi! My name is {}", name)) } } From 5e1ca4b99577578a1c92d71eeba49d88f60dcedc Mon Sep 17 00:00:00 2001 From: Noah Cairns Date: Wed, 15 Jun 2022 09:40:30 -0400 Subject: [PATCH 41/71] fix(errors5): improve exercise instructions --- exercises/error_handling/errors5.rs | 16 +++++++++++++--- info.toml | 19 +++++++------------ 2 files changed, 20 insertions(+), 15 deletions(-) diff --git a/exercises/error_handling/errors5.rs b/exercises/error_handling/errors5.rs index 365a8691..9d5ee4b7 100644 --- a/exercises/error_handling/errors5.rs +++ b/exercises/error_handling/errors5.rs @@ -1,7 +1,17 @@ // errors5.rs -// This program uses a completed version of the code from errors4. -// It won't compile right now! Why? +// This program uses an altered version of the code from errors4. + +// 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. + +// 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 +// type which implements a particular trait. To do so, The Box is declared as of type Box where Trait is the trait +// the compiler looks for on any value used in that context. For this exercise, that context is the potential errors +// which can be returned in a Result. + +// What can we use to describe both errors? In other words, is there a trait which both errors implement? + // Execute `rustlings hint errors5` for hints! // I AM NOT DONE @@ -11,7 +21,7 @@ use std::fmt; use std::num::ParseIntError; // TODO: update the return type of `main()` to make this compile. -fn main() -> Result<(), ParseIntError> { +fn main() -> Result<(), Box> { let pretend_user_input = "42"; let x: i64 = pretend_user_input.parse()?; println!("output={:?}", PositiveNonzeroInteger::new(x)?); diff --git a/info.toml b/info.toml index b13ed45e..97c174f5 100644 --- a/info.toml +++ b/info.toml @@ -619,22 +619,17 @@ name = "errors5" path = "exercises/error_handling/errors5.rs" mode = "compile" hint = """ -There are two different possible `Result` types produced within -`main()`, which are propagated using `?` operators. How do we declare a -return type from `main()` that allows both? +There are two different possible `Result` types produced within `main()`, which are +propagated using `?` operators. How do we declare a return type from `main()` that allows both? + +Under the hood, the `?` operator calls `From::from` on the error value to convert it to a boxed +trait object, a `Box`. This boxed trait object is polymorphic, and since all +errors implement the `error:Error` trait, we can capture lots of different errors in one "Box" +object. -Another hint: under the hood, the `?` operator calls `From::from` -on the error value to convert it to a boxed trait object, a -`Box`, which is polymorphic-- that means that lots of -different kinds of errors can be returned from the same function because -all errors act the same since they all implement the `error::Error` trait. Check out this section of the book: https://doc.rust-lang.org/book/ch09-02-recoverable-errors-with-result.html#a-shortcut-for-propagating-errors-the--operator -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. - Read more about boxing errors: https://doc.rust-lang.org/stable/rust-by-example/error/multiple_error_types/boxing_errors.html From c34e2adcbb261f71fbd013d61257457dd84bd849 Mon Sep 17 00:00:00 2001 From: mokou Date: Thu, 14 Jul 2022 18:02:33 +0200 Subject: [PATCH 42/71] feat(errors): Improve comments and hints --- exercises/error_handling/errors1.rs | 2 +- exercises/error_handling/errors2.rs | 3 ++- exercises/error_handling/errors3.rs | 2 +- exercises/error_handling/errors4.rs | 3 ++- exercises/error_handling/errors5.rs | 2 +- exercises/error_handling/errors6.rs | 6 +++++- info.toml | 5 ++++- 7 files changed, 16 insertions(+), 7 deletions(-) diff --git a/exercises/error_handling/errors1.rs b/exercises/error_handling/errors1.rs index 1a2a8577..bcee9723 100644 --- a/exercises/error_handling/errors1.rs +++ b/exercises/error_handling/errors1.rs @@ -3,7 +3,7 @@ // you pass it an empty string. It'd be nicer if it explained what the problem // was, instead of just sometimes returning `None`. Thankfully, Rust has a similar // construct to `Option` that can be used to express error conditions. Let's use it! -// Execute `rustlings hint errors1` for hints! +// Execute `rustlings hint errors1` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/exercises/error_handling/errors2.rs b/exercises/error_handling/errors2.rs index aad3a93f..1cd8fc66 100644 --- a/exercises/error_handling/errors2.rs +++ b/exercises/error_handling/errors2.rs @@ -14,7 +14,8 @@ // and add. // There are at least two ways to implement this that are both correct-- but -// one is a lot shorter! Execute `rustlings hint errors2` for hints to both ways. +// one is a lot shorter! +// Execute `rustlings hint errors2` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/exercises/error_handling/errors3.rs b/exercises/error_handling/errors3.rs index 460ac5c4..a2d2d190 100644 --- a/exercises/error_handling/errors3.rs +++ b/exercises/error_handling/errors3.rs @@ -2,7 +2,7 @@ // This is a program that is trying to use a completed version of the // `total_cost` function from the previous exercise. It's not working though! // Why not? What should we do to fix it? -// Execute `rustlings hint errors3` for hints! +// Execute `rustlings hint errors3` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/exercises/error_handling/errors4.rs b/exercises/error_handling/errors4.rs index 0685c374..0efe8ccd 100644 --- a/exercises/error_handling/errors4.rs +++ b/exercises/error_handling/errors4.rs @@ -1,5 +1,5 @@ // errors4.rs -// Make this test pass! Execute `rustlings hint errors4` for hints :) +// Execute `rustlings hint errors4` or use the `hint` watch subcommand for a hint. // I AM NOT DONE @@ -14,6 +14,7 @@ enum CreationError { impl PositiveNonzeroInteger { fn new(value: i64) -> Result { + // Hmm...? Why is this only returning an Ok value? Ok(PositiveNonzeroInteger(value as u64)) } } diff --git a/exercises/error_handling/errors5.rs b/exercises/error_handling/errors5.rs index 9d5ee4b7..67411c58 100644 --- a/exercises/error_handling/errors5.rs +++ b/exercises/error_handling/errors5.rs @@ -12,7 +12,7 @@ // What can we use to describe both errors? In other words, is there a trait which both errors implement? -// Execute `rustlings hint errors5` for hints! +// Execute `rustlings hint errors5` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/exercises/error_handling/errors6.rs b/exercises/error_handling/errors6.rs index 847a049a..1306fb03 100644 --- a/exercises/error_handling/errors6.rs +++ b/exercises/error_handling/errors6.rs @@ -6,7 +6,7 @@ // we define a custom error type to make it possible for callers to decide // what to do next when our function returns an error. -// Make these tests pass! Execute `rustlings hint errors6` for hints :) +// Execute `rustlings hint errors6` or use the `hint` watch subcommand for a hint. // I AM NOT DONE @@ -20,7 +20,11 @@ enum ParsePosNonzeroError { } impl ParsePosNonzeroError { + fn from_creation(err: CreationError) -> ParsePosNonzeroError { + ParsePosNonzeroError::Creation(err) + } // TODO: add another error conversion function here. + // fn from_parseint... } fn parse_pos_nonzero(s: &str) diff --git a/info.toml b/info.toml index 97c174f5..cb49a973 100644 --- a/info.toml +++ b/info.toml @@ -603,7 +603,10 @@ name = "errors3" path = "exercises/error_handling/errors3.rs" mode = "compile" hint = """ -If other functions can return a `Result`, why shouldn't `main`?""" +If other functions can return a `Result`, why shouldn't `main`? It's a fairly common +convention to return something like Result<(), ErrorType> from your main function. +The unit (`()`) type is there because nothing is really needed in terms of positive +results.""" [[exercises]] name = "errors4" From d61f79595a8929c118e76f78c6ec26ca49219062 Mon Sep 17 00:00:00 2001 From: mokou Date: Thu, 14 Jul 2022 18:11:05 +0200 Subject: [PATCH 43/71] feat(generics): add hint comments --- exercises/generics/generics1.rs | 2 +- exercises/generics/generics2.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/exercises/generics/generics1.rs b/exercises/generics/generics1.rs index f93e64a0..4c34ae47 100644 --- a/exercises/generics/generics1.rs +++ b/exercises/generics/generics1.rs @@ -1,7 +1,7 @@ // This shopping list program isn't compiling! // Use your knowledge of generics to fix it. -// Execute `rustlings hint generics1` for hints! +// Execute `rustlings hint generics1` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/exercises/generics/generics2.rs b/exercises/generics/generics2.rs index 1501529c..aedbd55c 100644 --- a/exercises/generics/generics2.rs +++ b/exercises/generics/generics2.rs @@ -1,7 +1,7 @@ // This powerful wrapper provides the ability to store a positive integer value. // Rewrite it using generics so that it supports wrapping ANY type. -// Execute `rustlings hint generics2` for hints! +// Execute `rustlings hint generics2` or use the `hint` watch subcommand for a hint. // I AM NOT DONE From 5979d408a9d3f174bf748b82d1a031a25b548af6 Mon Sep 17 00:00:00 2001 From: mokou Date: Thu, 14 Jul 2022 18:11:18 +0200 Subject: [PATCH 44/71] feat: move generics3 to be quiz3 --- exercises/generics/generics3.rs | 58 --------------------------------- exercises/quiz3.rs | 58 +++++++++++++++++++++++++-------- info.toml | 31 ++++++------------ 3 files changed, 55 insertions(+), 92 deletions(-) delete mode 100644 exercises/generics/generics3.rs diff --git a/exercises/generics/generics3.rs b/exercises/generics/generics3.rs deleted file mode 100644 index 64dd9bc1..00000000 --- a/exercises/generics/generics3.rs +++ /dev/null @@ -1,58 +0,0 @@ -// An imaginary magical school has a new report card generation system written in Rust! -// Currently the system only supports creating report cards where the student's grade -// is represented numerically (e.g. 1.0 -> 5.5). -// However, the school also issues alphabetical grades (A+ -> F-) and needs -// to be able to print both types of report card! - -// Make the necessary code changes in the struct ReportCard and the impl block -// to support alphabetical report cards. Change the Grade in the second test to "A+" -// to show that your changes allow alphabetical grades. - -// Execute 'rustlings hint generics3' for hints! - -// I AM NOT DONE - -pub struct ReportCard { - pub grade: f32, - pub student_name: String, - pub student_age: u8, -} - -impl ReportCard { - pub fn print(&self) -> String { - format!("{} ({}) - achieved a grade of {}", - &self.student_name, &self.student_age, &self.grade) - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn generate_numeric_report_card() { - let report_card = ReportCard { - grade: 2.1, - student_name: "Tom Wriggle".to_string(), - student_age: 12, - }; - assert_eq!( - report_card.print(), - "Tom Wriggle (12) - achieved a grade of 2.1" - ); - } - - #[test] - fn generate_alphabetic_report_card() { - // TODO: Make sure to change the grade here after you finish the exercise. - let report_card = ReportCard { - grade: 2.1, - student_name: "Gary Plotter".to_string(), - student_age: 11, - }; - assert_eq!( - report_card.print(), - "Gary Plotter (11) - achieved a grade of A+" - ); - } -} diff --git a/exercises/quiz3.rs b/exercises/quiz3.rs index fae0eedb..15dc4699 100644 --- a/exercises/quiz3.rs +++ b/exercises/quiz3.rs @@ -1,16 +1,32 @@ // quiz3.rs -// This is a quiz for the following sections: -// - Tests +// This quiz tests: +// - Generics +// - Traits +// An imaginary magical school has a new report card generation system written in Rust! +// Currently the system only supports creating report cards where the student's grade +// is represented numerically (e.g. 1.0 -> 5.5). +// However, the school also issues alphabetical grades (A+ -> F-) and needs +// to be able to print both types of report card! -// This quiz isn't testing our function -- make it do that in such a way that -// the test passes. Then write a second test that tests that we get the result -// we expect to get when we call `times_two` with a negative number. -// No hints, you can do this :) +// Make the necessary code changes in the struct ReportCard and the impl block +// to support alphabetical report cards. Change the Grade in the second test to "A+" +// to show that your changes allow alphabetical grades. + +// Execute `rustlings hint quiz3` or use the `hint` watch subcommand for a hint. // I AM NOT DONE -pub fn times_two(num: i32) -> i32 { - num * 2 +pub struct ReportCard { + pub grade: f32, + pub student_name: String, + pub student_age: u8, +} + +impl ReportCard { + pub fn print(&self) -> String { + format!("{} ({}) - achieved a grade of {}", + &self.student_name, &self.student_age, &self.grade) + } } #[cfg(test)] @@ -18,13 +34,29 @@ mod tests { use super::*; #[test] - fn returns_twice_of_positive_numbers() { - assert_eq!(times_two(4), ???); + fn generate_numeric_report_card() { + let report_card = ReportCard { + grade: 2.1, + student_name: "Tom Wriggle".to_string(), + student_age: 12, + }; + assert_eq!( + report_card.print(), + "Tom Wriggle (12) - achieved a grade of 2.1" + ); } #[test] - fn returns_twice_of_negative_numbers() { - // TODO replace unimplemented!() with an assert for `times_two(-4)` - unimplemented!() + fn generate_alphabetic_report_card() { + // TODO: Make sure to change the grade here after you finish the exercise. + let report_card = ReportCard { + grade: 2.1, + student_name: "Gary Plotter".to_string(), + student_age: 11, + }; + assert_eq!( + report_card.print(), + "Gary Plotter (11) - achieved a grade of A+" + ); } } diff --git a/info.toml b/info.toml index cb49a973..70f66e02 100644 --- a/info.toml +++ b/info.toml @@ -681,19 +681,6 @@ Maybe we could update the explicit references to this data type somehow? If you are still stuck https://doc.rust-lang.org/stable/book/ch10-01-syntax.html#in-method-definitions """ -[[exercises]] -name = "generics3" -path = "exercises/generics/generics3.rs" -mode = "test" -hint = """ -To find the best solution to this challenge you're going to need to think back to your -knowledge of traits, specifically Trait Bound Syntax - you may also need this: "use std::fmt::Display;" - -This is definitely harder than the last two exercises! You need to think about not only making the -ReportCard struct generic, but also the correct property - you will need to change the implementation -of the struct slightly too...you can do it! -""" - # TRAITS [[exercises]] @@ -716,6 +703,16 @@ Try mutating the incoming string vector. Vectors provide suitable methods for adding an element at the end. See the documentation at: https://doc.rust-lang.org/std/vec/struct.Vec.html""" +# QUIZ 3 + +[[exercises]] +name = "quiz3" +path = "exercises/quiz3.rs" +mode = "test" +hint = """ +To find the best solution to this challenge you're going to need to think back to your +knowledge of traits, specifically Trait Bound Syntax - you may also need this: "use std::fmt::Display;"""" + # TESTS [[exercises]] @@ -748,14 +745,6 @@ You can call a function right where you're passing arguments to `assert!` -- so something like `assert!(having_fun())`. If you want to check that you indeed get false, you can negate the result of what you're doing using `!`, like `assert!(!having_fun())`.""" -# TEST 3 - -[[exercises]] -name = "quiz3" -path = "exercises/quiz3.rs" -mode = "test" -hint = "No hints this time ;)" - # STANDARD LIBRARY TYPES [[exercises]] From 98b8d3f17d770acf5e618f1e1e62696af6fb00cf Mon Sep 17 00:00:00 2001 From: mokou Date: Thu, 14 Jul 2022 18:14:41 +0200 Subject: [PATCH 45/71] feat(traits): add hint comments --- exercises/traits/traits1.rs | 1 + exercises/traits/traits2.rs | 1 + info.toml | 3 ++- 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/exercises/traits/traits1.rs b/exercises/traits/traits1.rs index 15e08f24..5b9d8d50 100644 --- a/exercises/traits/traits1.rs +++ b/exercises/traits/traits1.rs @@ -7,6 +7,7 @@ // The trait AppendBar has only one function, // which appends "Bar" to any object // implementing this trait. +// Execute `rustlings hint traits1` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/exercises/traits/traits2.rs b/exercises/traits/traits2.rs index 916c3c4b..708bb19a 100644 --- a/exercises/traits/traits2.rs +++ b/exercises/traits/traits2.rs @@ -9,6 +9,7 @@ // // No boiler plate code this time, // you can do this! +// Execute `rustlings hint traits2` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/info.toml b/info.toml index 70f66e02..0213878c 100644 --- a/info.toml +++ b/info.toml @@ -698,7 +698,8 @@ path = "exercises/traits/traits2.rs" mode = "test" hint = """ Notice how the trait takes ownership of 'self',and returns `Self'. -Try mutating the incoming string vector. +Try mutating the incoming string vector. Have a look at the tests to see +what the result should look like! Vectors provide suitable methods for adding an element at the end. See the documentation at: https://doc.rust-lang.org/std/vec/struct.Vec.html""" From 016d718a286f6ccacaecdaa81d9245e96424bae1 Mon Sep 17 00:00:00 2001 From: mokou Date: Thu, 14 Jul 2022 18:15:47 +0200 Subject: [PATCH 46/71] feat(tests): add hint comments --- exercises/tests/tests1.rs | 3 ++- exercises/tests/tests2.rs | 3 ++- exercises/tests/tests3.rs | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/exercises/tests/tests1.rs b/exercises/tests/tests1.rs index 50586a19..8b6ea374 100644 --- a/exercises/tests/tests1.rs +++ b/exercises/tests/tests1.rs @@ -4,7 +4,8 @@ // rustlings run tests1 // This test has a problem with it -- make the test compile! Make the test -// pass! Make the test fail! Execute `rustlings hint tests1` for hints :) +// pass! Make the test fail! +// Execute `rustlings hint tests1` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/exercises/tests/tests2.rs b/exercises/tests/tests2.rs index 0d981ad1..a5ac15b1 100644 --- a/exercises/tests/tests2.rs +++ b/exercises/tests/tests2.rs @@ -1,6 +1,7 @@ // tests2.rs // This test has a problem with it -- make the test compile! Make the test -// pass! Make the test fail! Execute `rustlings hint tests2` for hints :) +// pass! Make the test fail! +// Execute `rustlings hint tests2` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/exercises/tests/tests3.rs b/exercises/tests/tests3.rs index 3424f940..196a81a0 100644 --- a/exercises/tests/tests3.rs +++ b/exercises/tests/tests3.rs @@ -2,7 +2,7 @@ // This test isn't testing our function -- make it do that in such a way that // the test passes. Then write a second test that tests whether we get the result // we expect to get when we call `is_even(5)`. -// Execute `rustlings hint tests3` for hints :) +// Execute `rustlings hint tests3` or use the `hint` watch subcommand for a hint. // I AM NOT DONE From cf9629cb0ea54220085cc33257613157ac830ab1 Mon Sep 17 00:00:00 2001 From: mokou Date: Thu, 14 Jul 2022 18:17:23 +0200 Subject: [PATCH 47/71] feat: move box/arc behind iterators --- exercises/standard_library_types/arc1.rs | 2 +- exercises/standard_library_types/box1.rs | 2 +- info.toml | 70 ++++++++++++------------ 3 files changed, 37 insertions(+), 37 deletions(-) diff --git a/exercises/standard_library_types/arc1.rs b/exercises/standard_library_types/arc1.rs index f60061e7..93a27036 100644 --- a/exercises/standard_library_types/arc1.rs +++ b/exercises/standard_library_types/arc1.rs @@ -16,7 +16,7 @@ // Make this code compile by filling in a value for `shared_numbers` where the // first TODO comment is, and create an initial binding for `child_numbers` // where the second TODO comment is. Try not to create any copies of the `numbers` Vec! -// Execute `rustlings hint arc1` for hints :) +// Execute `rustlings hint arc1` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/exercises/standard_library_types/box1.rs b/exercises/standard_library_types/box1.rs index f312f3d6..9d9237c1 100644 --- a/exercises/standard_library_types/box1.rs +++ b/exercises/standard_library_types/box1.rs @@ -14,7 +14,7 @@ // // Note: the tests should not be changed // -// Execute `rustlings hint box1` for hints :) +// Execute `rustlings hint box1` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/info.toml b/info.toml index 0213878c..1ba90d18 100644 --- a/info.toml +++ b/info.toml @@ -748,41 +748,6 @@ can negate the result of what you're doing using `!`, like `assert!(!having_fun( # STANDARD LIBRARY TYPES -[[exercises]] -name = "box1" -path = "exercises/standard_library_types/box1.rs" -mode = "test" -hint = """ -Step 1 -The compiler's message should help: since we cannot store the value of the actual type -when working with recursive types, we need to store a reference (pointer) to its value. -We should, therefore, place our `List` inside a `Box`. More details in the book here: -https://doc.rust-lang.org/book/ch15-01-box.html#enabling-recursive-types-with-boxes - -Step 2 -Creating an empty list should be fairly straightforward (hint: peek at the assertions). -For a non-empty list keep in mind that we want to use our Cons "list builder". -Although the current list is one of integers (i32), feel free to change the definition -and try other types! -""" - -[[exercises]] -name = "arc1" -path = "exercises/standard_library_types/arc1.rs" -mode = "compile" -hint = """ -Make `shared_numbers` be an `Arc` from the numbers vector. Then, in order -to avoid creating a copy of `numbers`, you'll need to create `child_numbers` -inside the loop but still in the main thread. - -`child_numbers` should be a clone of the Arc of the numbers instead of a -thread-local copy of the numbers. - -This is a simple exercise if you understand the underlying concepts, but if this -is too much of a struggle, consider reading through all of Chapter 16 in the book: -https://doc.rust-lang.org/stable/book/ch16-00-concurrency.html -""" - [[exercises]] name = "iterators1" path = "exercises/standard_library_types/iterators1.rs" @@ -868,6 +833,41 @@ 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.""" +[[exercises]] +name = "box1" +path = "exercises/standard_library_types/box1.rs" +mode = "test" +hint = """ +Step 1 +The compiler's message should help: since we cannot store the value of the actual type +when working with recursive types, we need to store a reference (pointer) to its value. +We should, therefore, place our `List` inside a `Box`. More details in the book here: +https://doc.rust-lang.org/book/ch15-01-box.html#enabling-recursive-types-with-boxes + +Step 2 +Creating an empty list should be fairly straightforward (hint: peek at the assertions). +For a non-empty list keep in mind that we want to use our Cons "list builder". +Although the current list is one of integers (i32), feel free to change the definition +and try other types! +""" + +[[exercises]] +name = "arc1" +path = "exercises/standard_library_types/arc1.rs" +mode = "compile" +hint = """ +Make `shared_numbers` be an `Arc` from the numbers vector. Then, in order +to avoid creating a copy of `numbers`, you'll need to create `child_numbers` +inside the loop but still in the main thread. + +`child_numbers` should be a clone of the Arc of the numbers instead of a +thread-local copy of the numbers. + +This is a simple exercise if you understand the underlying concepts, but if this +is too much of a struggle, consider reading through all of Chapter 16 in the book: +https://doc.rust-lang.org/stable/book/ch16-00-concurrency.html +""" + # THREADS [[exercises]] From 3c63ef06683410b63f191b3e43a7e499e9a02d33 Mon Sep 17 00:00:00 2001 From: Ryosuke YASUOKA Date: Fri, 14 Jan 2022 00:26:46 +0900 Subject: [PATCH 48/71] fix(iterators3): insert todo!() into divide() to compile without error --- exercises/standard_library_types/iterators3.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/exercises/standard_library_types/iterators3.rs b/exercises/standard_library_types/iterators3.rs index 8c66c05b..ec2e36d1 100644 --- a/exercises/standard_library_types/iterators3.rs +++ b/exercises/standard_library_types/iterators3.rs @@ -22,7 +22,9 @@ pub struct NotDivisibleError { // Calculate `a` divided by `b` if `a` is evenly divisible by `b`. // Otherwise, return a suitable error. -pub fn divide(a: i32, b: i32) -> Result {} +pub fn divide(a: i32, b: i32) -> Result { + todo!(); +} // Complete the function and return a value of the correct type so the test passes. // Desired output: Ok([1, 11, 1426, 3]) From 251d0dda345e6b3d067232a32db7afad098c8522 Mon Sep 17 00:00:00 2001 From: Paulo Gabriel Justino Bezerra Date: Thu, 13 Jan 2022 18:11:52 -0300 Subject: [PATCH 49/71] feat(iterators4): add factorial of zero test --- exercises/standard_library_types/iterators4.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/exercises/standard_library_types/iterators4.rs b/exercises/standard_library_types/iterators4.rs index 88862838..0b3b5d88 100644 --- a/exercises/standard_library_types/iterators4.rs +++ b/exercises/standard_library_types/iterators4.rs @@ -18,6 +18,11 @@ pub fn factorial(num: u64) -> u64 { mod tests { use super::*; + #[test] + fn factorial_of_0() { + assert_eq!(1, factorial(0)); + } + #[test] fn factorial_of_1() { assert_eq!(1, factorial(1)); From 20024d40c5e121202f283b420d7da1deecf4ebc0 Mon Sep 17 00:00:00 2001 From: mokou Date: Thu, 14 Jul 2022 18:29:09 +0200 Subject: [PATCH 50/71] feat(iterators): update hint comments --- exercises/standard_library_types/iterators1.rs | 2 +- exercises/standard_library_types/iterators2.rs | 2 +- exercises/standard_library_types/iterators3.rs | 2 +- exercises/standard_library_types/iterators4.rs | 1 + exercises/standard_library_types/iterators5.rs | 4 +++- info.toml | 7 +++++-- 6 files changed, 12 insertions(+), 6 deletions(-) diff --git a/exercises/standard_library_types/iterators1.rs b/exercises/standard_library_types/iterators1.rs index 5aa49b64..0379c6bb 100644 --- a/exercises/standard_library_types/iterators1.rs +++ b/exercises/standard_library_types/iterators1.rs @@ -6,7 +6,7 @@ // This module helps you get familiar with the structure of using an iterator and // how to go through elements within an iterable collection. // -// Execute `rustlings hint iterators1` for hints :D +// Execute `rustlings hint iterators1` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/exercises/standard_library_types/iterators2.rs b/exercises/standard_library_types/iterators2.rs index 87b4eaa1..29c53afb 100644 --- a/exercises/standard_library_types/iterators2.rs +++ b/exercises/standard_library_types/iterators2.rs @@ -1,7 +1,7 @@ // iterators2.rs // In this exercise, you'll learn some of the unique advantages that iterators // can offer. Follow the steps to complete the exercise. -// As always, there are hints if you execute `rustlings hint iterators2`! +// Execute `rustlings hint iterators2` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/exercises/standard_library_types/iterators3.rs b/exercises/standard_library_types/iterators3.rs index ec2e36d1..c97a6258 100644 --- a/exercises/standard_library_types/iterators3.rs +++ b/exercises/standard_library_types/iterators3.rs @@ -4,7 +4,7 @@ // 1. Complete the divide function to get the first four tests to pass. // 2. Get the remaining tests to pass by completing the result_with_list and // list_of_results functions. -// Execute `rustlings hint iterators3` to get some hints! +// Execute `rustlings hint iterators3` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/exercises/standard_library_types/iterators4.rs b/exercises/standard_library_types/iterators4.rs index 0b3b5d88..a02470ec 100644 --- a/exercises/standard_library_types/iterators4.rs +++ b/exercises/standard_library_types/iterators4.rs @@ -1,4 +1,5 @@ // iterators4.rs +// Execute `rustlings hint iterators4` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/exercises/standard_library_types/iterators5.rs b/exercises/standard_library_types/iterators5.rs index 93f3ae11..0593d123 100644 --- a/exercises/standard_library_types/iterators5.rs +++ b/exercises/standard_library_types/iterators5.rs @@ -6,7 +6,7 @@ // imperative style for loops. Recreate this counting functionality using // iterators. Only the two iterator methods (count_iterator and // count_collection_iterator) need to be modified. -// Execute `rustlings hint iterators5` for hints. +// Execute `rustlings hint iterators5` or use the `hint` watch subcommand for a hint. // // Make the code compile and the tests pass. @@ -34,6 +34,7 @@ fn count_for(map: &HashMap, value: Progress) -> usize { fn count_iterator(map: &HashMap, value: Progress) -> usize { // map is a hashmap with String keys and Progress values. // map = { "variables1": Complete, "from_str": None, ... } + todo!(); } fn count_collection_for(collection: &[HashMap], value: Progress) -> usize { @@ -52,6 +53,7 @@ fn count_collection_iterator(collection: &[HashMap], value: Pr // collection is a slice of hashmaps. // collection = [{ "variables1": Complete, "from_str": None, ... }, // { "variables2": Complete, ... }, ... ] + todo!(); } #[cfg(test)] diff --git a/info.toml b/info.toml index 1ba90d18..33f126e1 100644 --- a/info.toml +++ b/info.toml @@ -802,7 +802,8 @@ case is a vector of integers and the failure case is a DivisionError. The list_of_results function needs to return a vector of results. See https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.collect for how -the `FromIterator` trait is used in `collect()`.""" +the `FromIterator` trait is used in `collect()`. This trait is REALLY powerful! It +can make the solution to this exercise infinitely easier.""" [[exercises]] name = "iterators4" @@ -812,7 +813,9 @@ hint = """ In an imperative language, you might write a for loop that updates a mutable variable. Or, you might write code utilizing recursion and a match clause. In Rust you can take another functional -approach, computing the factorial elegantly with ranges and iterators.""" +approach, computing the factorial elegantly with ranges and iterators. + +Hint 2: Check out the `fold` and `rfold` methods!""" [[exercises]] name = "iterators5" From b4f52cb937e9f2b90913402964ae014240705a5f Mon Sep 17 00:00:00 2001 From: jaystile <46078028+jaystile@users.noreply.github.com> Date: Thu, 23 Dec 2021 06:19:39 -0800 Subject: [PATCH 51/71] feat: Adding threads1.rs with a focus on JoinHandles and waiting for spawned threads to finish. Moved the original threads1.rs to threads2.rs with the focus on the Mutex and modifying shared data. #892 --- exercises/threads/threads1.rs | 39 +++++++++++++++++------------------ exercises/threads/threads2.rs | 34 ++++++++++++++++++++++++++++++ info.toml | 24 ++++++++++++++------- 3 files changed, 69 insertions(+), 28 deletions(-) create mode 100644 exercises/threads/threads2.rs diff --git a/exercises/threads/threads1.rs b/exercises/threads/threads1.rs index f31b317e..ddb61552 100644 --- a/exercises/threads/threads1.rs +++ b/exercises/threads/threads1.rs @@ -1,32 +1,31 @@ // threads1.rs -// Make this compile! Execute `rustlings hint threads1` for hints :) -// The idea is the thread spawned on line 22 is completing jobs while the main thread is -// monitoring progress until 10 jobs are completed. Because of the difference between the -// spawned threads' sleep time, and the waiting threads sleep time, when you see 6 lines -// of "waiting..." and the program ends without timing out when running, -// you've got it :) +// Make this compile and run! Execute 'rustlings hint threads1' for hints :) +// This program should wait until all the spawned threads have finished before exiting. // I AM NOT DONE -use std::sync::Arc; use std::thread; use std::time::Duration; -struct JobStatus { - jobs_completed: u32, -} fn main() { - let status = Arc::new(JobStatus { jobs_completed: 0 }); - let status_shared = status.clone(); - thread::spawn(move || { - for _ in 0..10 { + + let mut handles = vec![]; + for i in 0..10 { + thread::spawn(move || { thread::sleep(Duration::from_millis(250)); - status_shared.jobs_completed += 1; - } - }); - while status.jobs_completed < 10 { - println!("waiting... "); - thread::sleep(Duration::from_millis(500)); + println!("thread {} is complete", i); + }); } + + let mut completed_threads = 0; + for handle in handles { + // TODO: a struct is returned from thread::spawn, can you use it? + completed_threads += 1; + } + + if completed_threads != 10 { + panic!("Oh no! All the spawned threads did not finish!"); + } + } diff --git a/exercises/threads/threads2.rs b/exercises/threads/threads2.rs new file mode 100644 index 00000000..2cb0d041 --- /dev/null +++ b/exercises/threads/threads2.rs @@ -0,0 +1,34 @@ +// threads2.rs +// Make this compile! Execute `rustlings hint threads2` for hints :) +// Building on the last exercise, we want all of the threads to complete their work but this time +// the spawned threads need to be in charge of updating a shared value: JobStatus.jobs_completed + +// I AM NOT DONE + +use std::sync::Arc; +use std::thread; +use std::time::Duration; + +struct JobStatus { + jobs_completed: u32, +} + +fn main() { + let status = Arc::new(JobStatus { jobs_completed: 0 }); + let mut handles = vec![]; + for _ in 0..10 { + let status_shared = status.clone(); + let handle = thread::spawn(move || { + thread::sleep(Duration::from_millis(250)); + // TODO: You must take an action before you update a shared value + status_shared.jobs_completed += 1; + }); + handles.push(handle); + } + for handle in handles { + handle.join().unwrap(); + // TODO: Print the value of the JobStatus.jobs_completed. Did you notice anything + // interesting in the output? Do you have to 'join' on all the handles? + println!("jobs completed {}", ???); + } +} diff --git a/info.toml b/info.toml index 33f126e1..94d5bf86 100644 --- a/info.toml +++ b/info.toml @@ -878,6 +878,22 @@ 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-handle + +Collect the JoinHandles and wait for them to finish. +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 @@ -898,14 +914,6 @@ 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. -Ok, so, real talk, this was actually tricky for *me* to do too. And -I could see a lot of different problems you might run into, so at this -point I'm not sure which one you've hit :) - -Please open an issue if you're still running into a problem that -these hints are not helping you with, or if you've looked at the sample -answers and don't understand why they work and yours doesn't. - 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 :)""" From f99eafc56f49852d4b801b5c4cfedf47ef4968ae Mon Sep 17 00:00:00 2001 From: mokou Date: Fri, 15 Jul 2022 11:59:53 +0200 Subject: [PATCH 52/71] fix(threads): add hint comments --- exercises/threads/threads1.rs | 2 +- exercises/threads/threads2.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/exercises/threads/threads1.rs b/exercises/threads/threads1.rs index ddb61552..e59f4ce4 100644 --- a/exercises/threads/threads1.rs +++ b/exercises/threads/threads1.rs @@ -1,5 +1,5 @@ // threads1.rs -// Make this compile and run! Execute 'rustlings hint threads1' for hints :) +// Execute `rustlings hint threads1` or use the `hint` watch subcommand for a hint. // This program should wait until all the spawned threads have finished before exiting. // I AM NOT DONE diff --git a/exercises/threads/threads2.rs b/exercises/threads/threads2.rs index 2cb0d041..d0f8578f 100644 --- a/exercises/threads/threads2.rs +++ b/exercises/threads/threads2.rs @@ -1,5 +1,5 @@ // threads2.rs -// Make this compile! Execute `rustlings hint threads2` for hints :) +// Execute `rustlings hint threads2` or use the `hint` watch subcommand for a hint. // Building on the last exercise, we want all of the threads to complete their work but this time // the spawned threads need to be in charge of updating a shared value: JobStatus.jobs_completed From d3a335bc64234738adb9d7514a5930bd6f9d38ee Mon Sep 17 00:00:00 2001 From: mokou Date: Fri, 15 Jul 2022 12:05:26 +0200 Subject: [PATCH 53/71] feat(macros): add hint comments --- exercises/macros/macros1.rs | 2 +- exercises/macros/macros2.rs | 2 +- exercises/macros/macros3.rs | 2 +- exercises/macros/macros4.rs | 2 +- info.toml | 7 ++++++- 5 files changed, 10 insertions(+), 5 deletions(-) diff --git a/exercises/macros/macros1.rs b/exercises/macros/macros1.rs index ed0dac85..634d0a70 100644 --- a/exercises/macros/macros1.rs +++ b/exercises/macros/macros1.rs @@ -1,5 +1,5 @@ // macros1.rs -// Make me compile! Execute `rustlings hint macros1` for hints :) +// Execute `rustlings hint macros1` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/exercises/macros/macros2.rs b/exercises/macros/macros2.rs index d0be1236..f6092cab 100644 --- a/exercises/macros/macros2.rs +++ b/exercises/macros/macros2.rs @@ -1,5 +1,5 @@ // macros2.rs -// Make me compile! Execute `rustlings hint macros2` for hints :) +// Execute `rustlings hint macros2` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/exercises/macros/macros3.rs b/exercises/macros/macros3.rs index 93a43113..106f1c6d 100644 --- a/exercises/macros/macros3.rs +++ b/exercises/macros/macros3.rs @@ -1,6 +1,6 @@ // macros3.rs // Make me compile, without taking the macro out of the module! -// Execute `rustlings hint macros3` for hints :) +// Execute `rustlings hint macros3` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/exercises/macros/macros4.rs b/exercises/macros/macros4.rs index 3a748078..c1fc5e8b 100644 --- a/exercises/macros/macros4.rs +++ b/exercises/macros/macros4.rs @@ -1,5 +1,5 @@ // macros4.rs -// Make me compile! Execute `rustlings hint macros4` for hints :) +// Execute `rustlings hint macros4` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/info.toml b/info.toml index 94d5bf86..1e7fa1ad 100644 --- a/info.toml +++ b/info.toml @@ -958,7 +958,12 @@ mode = "compile" hint = """ You only need to add a single character to make this compile. The way macros are written, it wants to see something between each -"macro arm", so it can separate them.""" +"macro arm", so it can separate them. + +That's all the macro exercises we have in here, but it's barely even +scratching the surface of what you can do with Rust's macros. For a more +thorough introduction, you can have a read through the little book of Rust +macros: https://veykril.github.io/tlborm/""" # TEST 4 From 7fc393bed4689d4e106a199dd956bef796976935 Mon Sep 17 00:00:00 2001 From: mokou Date: Fri, 15 Jul 2022 12:13:40 +0200 Subject: [PATCH 54/71] chore: remove quiz4 --- exercises/quiz4.rs | 23 ----------------------- info.toml | 8 -------- 2 files changed, 31 deletions(-) delete mode 100644 exercises/quiz4.rs diff --git a/exercises/quiz4.rs b/exercises/quiz4.rs deleted file mode 100644 index 6c47480d..00000000 --- a/exercises/quiz4.rs +++ /dev/null @@ -1,23 +0,0 @@ -// quiz4.rs -// This quiz covers the sections: -// - Modules -// - Macros - -// Write a macro that passes the quiz! No hints this time, you can do it! - -// I AM NOT DONE - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_my_macro_world() { - assert_eq!(my_macro!("world!"), "Hello world!"); - } - - #[test] - fn test_my_macro_goodbye() { - assert_eq!(my_macro!("goodbye!"), "Hello goodbye!"); - } -} diff --git a/info.toml b/info.toml index 1e7fa1ad..95674955 100644 --- a/info.toml +++ b/info.toml @@ -965,14 +965,6 @@ scratching the surface of what you can do with Rust's macros. For a more thorough introduction, you can have a read through the little book of Rust macros: https://veykril.github.io/tlborm/""" -# TEST 4 - -[[exercises]] -name = "quiz4" -path = "exercises/quiz4.rs" -mode = "test" -hint = "No hints this time ;)" - # CLIPPY [[exercises]] From 8cfedb16738e613ab90894386e299f5cb6292932 Mon Sep 17 00:00:00 2001 From: mokou Date: Fri, 15 Jul 2022 12:28:47 +0200 Subject: [PATCH 55/71] feat(clippy): add clippy3 --- .gitignore | 1 + exercises/clippy/clippy1.rs | 2 +- exercises/clippy/clippy2.rs | 2 +- exercises/clippy/clippy3.rs | 26 ++++++++++++++++++++++++++ info.toml | 6 ++++++ 5 files changed, 35 insertions(+), 2 deletions(-) create mode 100644 exercises/clippy/clippy3.rs diff --git a/.gitignore b/.gitignore index 253d85bd..534453bc 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,4 @@ rust-project.json .idea .vscode *.iml +*.o diff --git a/exercises/clippy/clippy1.rs b/exercises/clippy/clippy1.rs index c5f84a9c..bad46891 100644 --- a/exercises/clippy/clippy1.rs +++ b/exercises/clippy/clippy1.rs @@ -4,7 +4,7 @@ // // For these exercises the code will fail to compile when there are clippy warnings // check clippy's suggestions from the output to solve the exercise. -// Execute `rustlings hint clippy1` for hints :) +// Execute `rustlings hint clippy1` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/exercises/clippy/clippy2.rs b/exercises/clippy/clippy2.rs index 37af9ed0..dac40dbe 100644 --- a/exercises/clippy/clippy2.rs +++ b/exercises/clippy/clippy2.rs @@ -1,5 +1,5 @@ // clippy2.rs -// Make me compile! Execute `rustlings hint clippy2` for hints :) +// Execute `rustlings hint clippy2` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/exercises/clippy/clippy3.rs b/exercises/clippy/clippy3.rs new file mode 100644 index 00000000..13733c0b --- /dev/null +++ b/exercises/clippy/clippy3.rs @@ -0,0 +1,26 @@ +// clippy3.rs +// Here's a couple more easy Clippy fixes, so you can see its utility. + +#[allow(unused_variables, unused_assignments)] +fn main() { + let my_option: Option<()> = None; + if my_option.is_none() { + my_option.unwrap(); + } + + let my_arr = &[ + -1, -2, -3 + -4, -5, -6 + ]; + println!("My array! Here it is: {:?}", my_arr); + + let my_empty_vec = vec![1, 2, 3, 4, 5].resize(0, 5); + println!("This Vec is empty, see? {:?}", my_empty_vec); + + let mut value_a = 45; + let mut value_b = 66; + // Let's swap these two! + value_a = value_b; + value_b = value_a; + println!("value a: {}; value b: {}", value_a, value_b); +} diff --git a/info.toml b/info.toml index 95674955..3c37f95b 100644 --- a/info.toml +++ b/info.toml @@ -989,6 +989,12 @@ mode = "clippy" hint = """ `for` loops over Option values are more clearly expressed as an `if let`""" +[[exercises]] +name = "clippy3" +path = "exercises/clippy/clippy3.rs" +mode = "clippy" +hint = "No hints this time!" + # TYPE CONVERSIONS [[exercises]] From 74f44f55e381384dc89ec421568aa1509cd7f277 Mon Sep 17 00:00:00 2001 From: mokou Date: Fri, 15 Jul 2022 12:34:10 +0200 Subject: [PATCH 56/71] feat(conversions): add hint comments --- exercises/conversions/from_into.rs | 2 ++ exercises/conversions/from_str.rs | 5 +++++ exercises/conversions/try_from_into.rs | 2 ++ exercises/conversions/using_as.rs | 1 + 4 files changed, 10 insertions(+) diff --git a/exercises/conversions/from_into.rs b/exercises/conversions/from_into.rs index 9d84174d..6c272c3b 100644 --- a/exercises/conversions/from_into.rs +++ b/exercises/conversions/from_into.rs @@ -1,6 +1,8 @@ // The From trait is used for value-to-value conversions. // If From is implemented correctly for a type, the Into trait should work conversely. // You can read more about it at https://doc.rust-lang.org/std/convert/trait.From.html +// Execute `rustlings hint from_into` or use the `hint` watch subcommand for a hint. + #[derive(Debug)] struct Person { name: String, diff --git a/exercises/conversions/from_str.rs b/exercises/conversions/from_str.rs index ece0b3cf..fe168159 100644 --- a/exercises/conversions/from_str.rs +++ b/exercises/conversions/from_str.rs @@ -4,6 +4,8 @@ // Additionally, upon implementing FromStr, you can use the `parse` method // on strings to generate an object of the implementor type. // You can read more about it at https://doc.rust-lang.org/std/str/trait.FromStr.html +// Execute `rustlings hint from_str` or use the `hint` watch subcommand for a hint. + use std::num::ParseIntError; use std::str::FromStr; @@ -37,6 +39,9 @@ enum ParsePersonError { // with something like `"4".parse::()` // 6. If while extracting the name and the age something goes wrong, an error should be returned // If everything goes well, then return a Result of a Person object +// +// As an aside: `Box` implements `From<&'_ str>`. This means that if you want to return a +// string error message, you can do so via just using return `Err("my error message".into())`. impl FromStr for Person { type Err = ParsePersonError; diff --git a/exercises/conversions/try_from_into.rs b/exercises/conversions/try_from_into.rs index b8ec4455..09f730eb 100644 --- a/exercises/conversions/try_from_into.rs +++ b/exercises/conversions/try_from_into.rs @@ -3,6 +3,8 @@ // Basically, this is the same as From. The main difference is that this should return a Result type // instead of the target type itself. // You can read more about it at https://doc.rust-lang.org/std/convert/trait.TryFrom.html +// Execute `rustlings hint from_str` or use the `hint` watch subcommand for a hint. + use std::convert::{TryFrom, TryInto}; #[derive(Debug, PartialEq)] diff --git a/exercises/conversions/using_as.rs b/exercises/conversions/using_as.rs index f3f745ff..8c9b7113 100644 --- a/exercises/conversions/using_as.rs +++ b/exercises/conversions/using_as.rs @@ -4,6 +4,7 @@ // // The goal is to make sure that the division does not fail to compile // and returns the proper type. +// Execute `rustlings hint using_as` or use the `hint` watch subcommand for a hint. // I AM NOT DONE From 81d25aecff01643221131743b48f6b63377eeb59 Mon Sep 17 00:00:00 2001 From: mokou Date: Fri, 15 Jul 2022 12:49:49 +0200 Subject: [PATCH 57/71] feat(try_from_into): add hint comments --- exercises/conversions/try_from_into.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exercises/conversions/try_from_into.rs b/exercises/conversions/try_from_into.rs index 09f730eb..bc71a3c3 100644 --- a/exercises/conversions/try_from_into.rs +++ b/exercises/conversions/try_from_into.rs @@ -3,7 +3,7 @@ // Basically, this is the same as From. The main difference is that this should return a Result type // instead of the target type itself. // You can read more about it at https://doc.rust-lang.org/std/convert/trait.TryFrom.html -// Execute `rustlings hint from_str` or use the `hint` watch subcommand for a hint. +// Execute `rustlings hint try_from_into` or use the `hint` watch subcommand for a hint. use std::convert::{TryFrom, TryInto}; From 4bebdb5f02f492081568900b739ad76dc05ea4ef Mon Sep 17 00:00:00 2001 From: mokou Date: Fri, 15 Jul 2022 12:50:01 +0200 Subject: [PATCH 58/71] feat(as_ref_mut): add AsMut section --- exercises/conversions/as_ref_mut.rs | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/exercises/conversions/as_ref_mut.rs b/exercises/conversions/as_ref_mut.rs index 84f4a60c..9f479739 100644 --- a/exercises/conversions/as_ref_mut.rs +++ b/exercises/conversions/as_ref_mut.rs @@ -1,6 +1,7 @@ // AsRef and AsMut allow for cheap reference-to-reference conversions. // Read more about them at https://doc.rust-lang.org/std/convert/trait.AsRef.html // and https://doc.rust-lang.org/std/convert/trait.AsMut.html, respectively. +// Execute `rustlings hint as_ref_mut` or use the `hint` watch subcommand for a hint. // I AM NOT DONE @@ -16,10 +17,10 @@ fn char_counter(arg: T) -> usize { arg.as_ref().chars().count() } -fn main() { - let s = "Café au lait"; - println!("{}", char_counter(s)); - println!("{}", byte_counter(s)); +// Squares a number using AsMut. Add the trait bound as is appropriate and +// implement the function body. +fn num_sq(arg: &mut T) { + ??? } #[cfg(test)] @@ -49,4 +50,11 @@ mod tests { let s = String::from("Cafe au lait"); assert_eq!(char_counter(s.clone()), byte_counter(s)); } + + #[test] + fn mult_box() { + let mut num: Box = Box::new(3); + num_sq(&mut num); + assert_eq!(*num, 9); + } } From b609f0431c0031c8aa9113fea4de4b23db05cf77 Mon Sep 17 00:00:00 2001 From: mokou Date: Fri, 15 Jul 2022 12:51:12 +0200 Subject: [PATCH 59/71] feat: remove advanced_errs --- exercises/advanced_errors/advanced_errs1.rs | 98 ---------- exercises/advanced_errors/advanced_errs2.rs | 202 -------------------- info.toml | 52 ----- 3 files changed, 352 deletions(-) delete mode 100644 exercises/advanced_errors/advanced_errs1.rs delete mode 100644 exercises/advanced_errors/advanced_errs2.rs diff --git a/exercises/advanced_errors/advanced_errs1.rs b/exercises/advanced_errors/advanced_errs1.rs deleted file mode 100644 index 4bc7b635..00000000 --- a/exercises/advanced_errors/advanced_errs1.rs +++ /dev/null @@ -1,98 +0,0 @@ -// advanced_errs1.rs - -// Remember back in errors6, we had multiple mapping functions so that we -// could translate lower-level errors into our custom error type using -// `map_err()`? What if we could use the `?` operator directly instead? - -// Make this code compile! Execute `rustlings hint advanced_errs1` for -// hints :) - -// I AM NOT DONE - -use std::num::ParseIntError; -use std::str::FromStr; - -// This is a custom error type that we will be using in the `FromStr` -// implementation. -#[derive(PartialEq, Debug)] -enum ParsePosNonzeroError { - Creation(CreationError), - ParseInt(ParseIntError), -} - -impl From for ParsePosNonzeroError { - fn from(e: CreationError) -> Self { - // TODO: complete this implementation so that the `?` operator will - // work for `CreationError` - } -} - -// TODO: implement another instance of the `From` trait here so that the -// `?` operator will work in the other place in the `FromStr` -// implementation below. - -// Don't change anything below this line. - -impl FromStr for PositiveNonzeroInteger { - type Err = ParsePosNonzeroError; - fn from_str(s: &str) -> Result { - let x: i64 = s.parse()?; - Ok(PositiveNonzeroInteger::new(x)?) - } -} - -#[derive(PartialEq, Debug)] -struct PositiveNonzeroInteger(u64); - -#[derive(PartialEq, Debug)] -enum CreationError { - Negative, - Zero, -} - -impl PositiveNonzeroInteger { - fn new(value: i64) -> Result { - match value { - x if x < 0 => Err(CreationError::Negative), - x if x == 0 => Err(CreationError::Zero), - x => Ok(PositiveNonzeroInteger(x as u64)), - } - } -} - -#[cfg(test)] -mod test { - use super::*; - - #[test] - fn test_parse_error() { - // We can't construct a ParseIntError, so we have to pattern match. - assert!(matches!( - PositiveNonzeroInteger::from_str("not a number"), - Err(ParsePosNonzeroError::ParseInt(_)) - )); - } - - #[test] - fn test_negative() { - assert_eq!( - PositiveNonzeroInteger::from_str("-555"), - Err(ParsePosNonzeroError::Creation(CreationError::Negative)) - ); - } - - #[test] - fn test_zero() { - assert_eq!( - PositiveNonzeroInteger::from_str("0"), - Err(ParsePosNonzeroError::Creation(CreationError::Zero)) - ); - } - - #[test] - fn test_positive() { - let x = PositiveNonzeroInteger::new(42); - assert!(x.is_ok()); - assert_eq!(PositiveNonzeroInteger::from_str("42"), Ok(x.unwrap())); - } -} diff --git a/exercises/advanced_errors/advanced_errs2.rs b/exercises/advanced_errors/advanced_errs2.rs deleted file mode 100644 index 54e669fd..00000000 --- a/exercises/advanced_errors/advanced_errs2.rs +++ /dev/null @@ -1,202 +0,0 @@ -// advanced_errs2.rs - -// This exercise demonstrates a few traits that are useful for custom error -// types to implement, especially so that other code can consume the custom -// error type more usefully. - -// Make this compile, and make the tests pass! -// Execute `rustlings hint advanced_errs2` for hints. - -// Steps: -// 1. Implement a missing trait so that `main()` will compile. -// 2. Complete the partial implementation of `From` for -// `ParseClimateError`. -// 3. Handle the missing error cases in the `FromStr` implementation for -// `Climate`. -// 4. Complete the partial implementation of `Display` for -// `ParseClimateError`. - -// I AM NOT DONE - -use std::error::Error; -use std::fmt::{self, Display, Formatter}; -use std::num::{ParseFloatError, ParseIntError}; -use std::str::FromStr; - -// This is the custom error type that we will be using for the parser for -// `Climate`. -#[derive(Debug, PartialEq)] -enum ParseClimateError { - Empty, - BadLen, - NoCity, - ParseInt(ParseIntError), - ParseFloat(ParseFloatError), -} - -// This `From` implementation allows the `?` operator to work on -// `ParseIntError` values. -impl From for ParseClimateError { - fn from(e: ParseIntError) -> Self { - Self::ParseInt(e) - } -} - -// This `From` implementation allows the `?` operator to work on -// `ParseFloatError` values. -impl From for ParseClimateError { - fn from(e: ParseFloatError) -> Self { - // TODO: Complete this function - } -} - -// TODO: Implement a missing trait so that `main()` below will compile. It -// is not necessary to implement any methods inside the missing trait. - -// The `Display` trait allows for other code to obtain the error formatted -// as a user-visible string. -impl Display for ParseClimateError { - // TODO: Complete this function so that it produces the correct strings - // for each error variant. - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - // Imports the variants to make the following code more compact. - use ParseClimateError::*; - match self { - NoCity => write!(f, "no city name"), - ParseFloat(e) => write!(f, "error parsing temperature: {}", e), - } - } -} - -#[derive(Debug, PartialEq)] -struct Climate { - city: String, - year: u32, - temp: f32, -} - -// Parser for `Climate`. -// 1. Split the input string into 3 fields: city, year, temp. -// 2. Return an error if the string is empty or has the wrong number of -// fields. -// 3. Return an error if the city name is empty. -// 4. Parse the year as a `u32` and return an error if that fails. -// 5. Parse the temp as a `f32` and return an error if that fails. -// 6. Return an `Ok` value containing the completed `Climate` value. -impl FromStr for Climate { - type Err = ParseClimateError; - // TODO: Complete this function by making it handle the missing error - // cases. - fn from_str(s: &str) -> Result { - let v: Vec<_> = s.split(',').collect(); - let (city, year, temp) = match &v[..] { - [city, year, temp] => (city.to_string(), year, temp), - _ => return Err(ParseClimateError::BadLen), - }; - let year: u32 = year.parse()?; - let temp: f32 = temp.parse()?; - Ok(Climate { city, year, temp }) - } -} - -// Don't change anything below this line (other than to enable ignored -// tests). - -fn main() -> Result<(), Box> { - println!("{:?}", "Hong Kong,1999,25.7".parse::()?); - println!("{:?}", "".parse::()?); - Ok(()) -} - -#[cfg(test)] -mod test { - use super::*; - #[test] - fn test_empty() { - let res = "".parse::(); - assert_eq!(res, Err(ParseClimateError::Empty)); - assert_eq!(res.unwrap_err().to_string(), "empty input"); - } - #[test] - fn test_short() { - let res = "Boston,1991".parse::(); - assert_eq!(res, Err(ParseClimateError::BadLen)); - assert_eq!(res.unwrap_err().to_string(), "incorrect number of fields"); - } - #[test] - fn test_long() { - let res = "Paris,1920,17.2,extra".parse::(); - assert_eq!(res, Err(ParseClimateError::BadLen)); - assert_eq!(res.unwrap_err().to_string(), "incorrect number of fields"); - } - #[test] - fn test_no_city() { - let res = ",1997,20.5".parse::(); - assert_eq!(res, Err(ParseClimateError::NoCity)); - assert_eq!(res.unwrap_err().to_string(), "no city name"); - } - #[test] - fn test_parse_int_neg() { - let res = "Barcelona,-25,22.3".parse::(); - assert!(matches!(res, Err(ParseClimateError::ParseInt(_)))); - let err = res.unwrap_err(); - if let ParseClimateError::ParseInt(ref inner) = err { - assert_eq!( - err.to_string(), - format!("error parsing year: {}", inner.to_string()) - ); - } else { - unreachable!(); - }; - } - #[test] - fn test_parse_int_bad() { - let res = "Beijing,foo,15.0".parse::(); - assert!(matches!(res, Err(ParseClimateError::ParseInt(_)))); - let err = res.unwrap_err(); - if let ParseClimateError::ParseInt(ref inner) = err { - assert_eq!( - err.to_string(), - format!("error parsing year: {}", inner.to_string()) - ); - } else { - unreachable!(); - }; - } - #[test] - fn test_parse_float() { - let res = "Manila,2001,bar".parse::(); - assert!(matches!(res, Err(ParseClimateError::ParseFloat(_)))); - let err = res.unwrap_err(); - if let ParseClimateError::ParseFloat(ref inner) = err { - assert_eq!( - err.to_string(), - format!("error parsing temperature: {}", inner.to_string()) - ); - } else { - unreachable!(); - }; - } - #[test] - fn test_parse_good() { - let res = "Munich,2015,23.1".parse::(); - assert_eq!( - res, - Ok(Climate { - city: "Munich".to_string(), - year: 2015, - temp: 23.1, - }) - ); - } - #[test] - #[ignore] - fn test_downcast() { - let res = "São Paulo,-21,28.5".parse::(); - assert!(matches!(res, Err(ParseClimateError::ParseInt(_)))); - let err = res.unwrap_err(); - let inner: Option<&(dyn Error + 'static)> = err.source(); - assert!(inner.is_some()); - assert!(inner.unwrap().is::()); - } -} diff --git a/info.toml b/info.toml index 3c37f95b..c239121d 100644 --- a/info.toml +++ b/info.toml @@ -1061,55 +1061,3 @@ path = "exercises/conversions/as_ref_mut.rs" mode = "test" hint = """ Add AsRef as a trait bound to the functions.""" - -# ADVANCED ERRORS - -[[exercises]] -name = "advanced_errs1" -path = "exercises/advanced_errors/advanced_errs1.rs" -mode = "test" -hint = """ -This exercise uses an updated version of the code in errors6. The parsing -code is now in an implementation of the `FromStr` trait. Note that the -parsing code uses `?` directly, without any calls to `map_err()`. There is -one partial implementation of the `From` trait example that you should -complete. - -Details: The `?` operator calls `From::from()` on the error type to convert -it to the error type of the return type of the surrounding function. - -Hint: You will need to write another implementation of `From` that has a -different input type. -""" - -[[exercises]] -name = "advanced_errs2" -path = "exercises/advanced_errors/advanced_errs2.rs" -mode = "test" -hint = """ -This exercise demonstrates a few traits that are useful for custom error -types to implement. These traits make it easier for other code to consume -the custom error type. - -Follow the steps in the comment near the top of the file. You will have to -supply a missing trait implementation, and complete a few incomplete ones. - -You may find these pages to be helpful references: -https://doc.rust-lang.org/stable/rust-by-example/error/multiple_error_types/define_error_type.html -https://doc.rust-lang.org/stable/rust-by-example/error/multiple_error_types/boxing_errors.html -https://doc.rust-lang.org/stable/rust-by-example/error/multiple_error_types/wrap_error.html - -Hint: What trait must our error type have for `main()` to return the return -type that it returns? - -Another hint: It's not necessary to implement any methods inside the missing -trait. (Some methods have default implementations that are supplied by the -trait.) - -Another hint: Consult the tests to determine which error variants (and which -error message text) to produce for certain error conditions. - -Challenge: There is one test that is marked `#[ignore]`. Can you supply the -missing code that will make it pass? You may want to consult the standard -library documentation for a certain trait for more hints. -""" From 0784f54141325bf9b6dbea886aaa5002f7cc9a75 Mon Sep 17 00:00:00 2001 From: mokou Date: Fri, 15 Jul 2022 12:57:54 +0200 Subject: [PATCH 60/71] doc: update contributing --- CONTRIBUTING.md | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 2ca0e341..cc8ac923 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -21,7 +21,7 @@ _implement a new feature! ➡️ [open an Issue to discuss it first, then a Pull `rustlings` is basically a glorified `rustc` wrapper. Therefore the source code isn't really that complicated since the bulk of the work is done by `rustc`. -`src/main.rs` contains a simple `clap` CLI that loads from `src/verify.rs` and `src/run.rs`. +`src/main.rs` contains a simple `argh` CLI that connects to most of the other source files. ### Adding an exercise @@ -29,7 +29,7 @@ isn't really that complicated since the bulk of the work is done by `rustc`. The first step is to add the exercise! Name the file `exercises/yourTopic/yourTopicN.rs`, make sure to put in some helpful links, and link to sections of the book in `exercises/yourTopic/README.md`. -Next make sure it runs with `rustlings`. The exercise metadata is stored in `info.toml`, under the `exercises` array. The order of the `exercises` array determines the order the exercises are run by `rustlings verify`. +Next make sure it runs with `rustlings`. The exercise metadata is stored in `info.toml`, under the `exercises` array. The order of the `exercises` array determines the order the exercises are run by `rustlings verify` and `rustlings watch`. Add the metadata for your exercise in the correct order in the `exercises` array. If you are unsure of the correct ordering, add it at the bottom and ask in your pull request. The exercise metadata should contain the following: ```diff @@ -43,7 +43,7 @@ Add the metadata for your exercise in the correct order in the `exercises` array ... ``` -The `mode` attribute decides whether Rustlings will only compile your exercise, or compile and test it. If you have tests to verify in your exercise, choose `test`, otherwise `compile`. +The `mode` attribute decides whether Rustlings will only compile your exercise, or compile and test it. If you have tests to verify in your exercise, choose `test`, otherwise `compile`. If you're working on a Clippy exercise, use `mode = "clippy"`. That's all! Feel free to put up a pull request. @@ -67,19 +67,19 @@ changes. There's a couple of things to watch out for: #### Write correct commit messages We follow the [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0-beta.4/) -specification, because it makes it easier to generate changelogs automatically. +specification. This means that you have to format your commit messages in a specific way. Say you're working on adding a new exercise called `foobar1.rs`. You could write the following commit message: ``` -feat: Add foobar1.rs exercise +feat: add foobar1.rs exercise ``` If you're just fixing a bug, please use the `fix` type: ``` -fix(verify): Make sure verify doesn't self-destruct +fix(verify): make sure verify doesn't self-destruct ``` The scope within the brackets is optional, but should be any of these: @@ -96,7 +96,7 @@ When the commit also happens to close an existing issue, link it in the message body: ``` -fix: Update foobar +fix: update foobar closes #101029908 ``` @@ -104,13 +104,13 @@ closes #101029908 If you're doing simple changes, like updating a book link, use `chore`: ``` -chore: Update exercise1.rs book link +chore: update exercise1.rs book link ``` If you're updating documentation, use `docs`: ``` -docs: Add more information to Readme +docs: add more information to Readme ``` If, and only if, you're absolutely sure you want to make a breaking change @@ -118,7 +118,7 @@ If, and only if, you're absolutely sure you want to make a breaking change explain the breaking change in the message body: ``` -fix!: Completely change verification +fix!: completely change verification BREAKING CHANGE: This has to be done because lorem ipsum dolor ``` @@ -126,6 +126,5 @@ BREAKING CHANGE: This has to be done because lorem ipsum dolor #### Pull Request Workflow Once you open a Pull Request, it may be reviewed or labeled (or both) until -the maintainers accept your change. Then, [bors](https://github.com/bors) will -run the test suite with your changes and if it's successful, automatically -merge it in! +the maintainers accept your change. Please be patient, it may take some time +for this to happen! From a6e86fc995f8e6555b80dc5e73b4d7d78c050706 Mon Sep 17 00:00:00 2001 From: mokou Date: Fri, 15 Jul 2022 13:22:29 +0200 Subject: [PATCH 61/71] doc: update readme --- README.md | 22 ++-------------------- 1 file changed, 2 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 12a77810..103aec8b 100644 --- a/README.md +++ b/README.md @@ -44,9 +44,9 @@ Start-BitsTransfer -Source https://raw.githubusercontent.com/rust-lang/rustlings To install Rustlings. Same as on MacOS/Linux, you will have access to the `rustlings` command after it. -When you get a permission denied message then you have to exclude the directory where you placed the rustlings in your virus-scanner +If you get a permission denied message, you might have to exclude the directory where you cloned Rustlings in your antivirus. -## Browser: +## Browser [Run on Repl.it](https://repl.it/github/rust-lang/rustlings) @@ -150,24 +150,6 @@ cargo uninstall rustlings Now you should be done! -## Completion - -Rustlings isn't done; there are a couple of sections that are very experimental and don't have proper documentation. These include: - -- Errors (`exercises/errors/`) -- Option (`exercises/option/`) -- Result (`exercises/result/`) -- Move Semantics (could still be improved, `exercises/move_semantics/`) - -Additionally, we could use exercises on a couple of topics: - -- Structs -- Better ownership stuff -- `impl` -- ??? probably more - -If you are interested in improving or adding new ones, please feel free to contribute! Read on for more information :) - ## Contributing See [CONTRIBUTING.md](./CONTRIBUTING.md). From a3c4c1ccb4d7de6638b296387607c0a44b10e11f Mon Sep 17 00:00:00 2001 From: mokou Date: Fri, 15 Jul 2022 13:24:11 +0200 Subject: [PATCH 62/71] fix: re-add missing done comments --- exercises/clippy/clippy3.rs | 2 ++ exercises/quiz2.rs | 2 ++ exercises/strings/strings3.rs | 2 ++ 3 files changed, 6 insertions(+) diff --git a/exercises/clippy/clippy3.rs b/exercises/clippy/clippy3.rs index 13733c0b..b0159ebe 100644 --- a/exercises/clippy/clippy3.rs +++ b/exercises/clippy/clippy3.rs @@ -1,6 +1,8 @@ // clippy3.rs // Here's a couple more easy Clippy fixes, so you can see its utility. +// I AM NOT DONE + #[allow(unused_variables, unused_assignments)] fn main() { let my_option: Option<()> = None; diff --git a/exercises/quiz2.rs b/exercises/quiz2.rs index 5d3ccc03..f7437fd2 100644 --- a/exercises/quiz2.rs +++ b/exercises/quiz2.rs @@ -18,6 +18,8 @@ // - The output element is going to be a Vector of strings. // Execute `rustlings hint quiz2` or use the `hint` watch subcommand for a hint. +// I AM NOT DONE + pub enum Command { Uppercase, Trim, diff --git a/exercises/strings/strings3.rs b/exercises/strings/strings3.rs index bb0a259e..9e25d307 100644 --- a/exercises/strings/strings3.rs +++ b/exercises/strings/strings3.rs @@ -1,6 +1,8 @@ // strings3.rs // Execute `rustlings hint strings3` or use the `hint` watch subcommand for a hint. +// I AM NOT DONE + fn trim_me(input: &str) -> String { // TODO: Remove whitespace from the end of a string! ??? From a3b5278b4259da83bad1f645e19ba6b0d36f4dde Mon Sep 17 00:00:00 2001 From: exdx Date: Fri, 15 Jul 2022 13:28:49 +0200 Subject: [PATCH 63/71] feat: add threads3.rs exercise --- exercises/threads/threads3.rs | 64 +++++++++++++++++++++++++++++++++++ info.toml | 14 ++++++++ 2 files changed, 78 insertions(+) create mode 100644 exercises/threads/threads3.rs diff --git a/exercises/threads/threads3.rs b/exercises/threads/threads3.rs new file mode 100644 index 00000000..27e99088 --- /dev/null +++ b/exercises/threads/threads3.rs @@ -0,0 +1,64 @@ +// threads3.rs +// Execute `rustlings hint threads3` or use the `hint` watch subcommand for a hint. + +// I AM NOT DONE + +use std::sync::mpsc; +use std::sync::Arc; +use std::thread; +use std::time::Duration; + +struct Queue { + length: u32, + first_half: Vec, + second_half: Vec, +} + +impl Queue { + fn new() -> Self { + Queue { + length: 10, + first_half: vec![1, 2, 3, 4, 5], + second_half: vec![6, 7, 8, 9, 10], + } + } +} + +fn send_tx(q: Queue, tx: mpsc::Sender) -> () { + let qc = Arc::new(q); + let qc1 = qc.clone(); + let qc2 = qc.clone(); + + thread::spawn(move || { + for val in &qc1.first_half { + println!("sending {:?}", val); + tx.send(*val).unwrap(); + thread::sleep(Duration::from_secs(1)); + } + }); + + thread::spawn(move || { + for val in &qc2.second_half { + println!("sending {:?}", val); + tx.send(*val).unwrap(); + thread::sleep(Duration::from_secs(1)); + } + }); +} + +fn main() { + let (tx, rx) = mpsc::channel(); + let queue = Queue::new(); + let queue_length = queue.length; + + send_tx(queue, tx); + + let mut total_received: u32 = 0; + for received in rx { + println!("Got: {}", received); + total_received += 1; + } + + println!("total numbers received: {}", total_received); + assert_eq!(total_received, queue_length) +} diff --git a/info.toml b/info.toml index c239121d..8871c15b 100644 --- a/info.toml +++ b/info.toml @@ -918,6 +918,20 @@ 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 receieve them in another. +Multiple producers are possibile 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]] From 1cc5df0e144ef3551062c162e2e1618c27d97ae0 Mon Sep 17 00:00:00 2001 From: James Zow Date: Fri, 15 Jul 2022 13:46:03 +0200 Subject: [PATCH 64/71] feat: add github actions config --- .github/workflows/rust.yml | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 .github/workflows/rust.yml diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml new file mode 100644 index 00000000..bf2a041a --- /dev/null +++ b/.github/workflows/rust.yml @@ -0,0 +1,20 @@ +name: Rustlings Tests + +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + +env: + CARGO_TERM_COLOR: always + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Build + run: cargo build --verbose + - name: Run tests + run: cargo test --verbose From 1ef8dacaf69e3ad1418355eeea128c00f09bdcb3 Mon Sep 17 00:00:00 2001 From: jayber Date: Fri, 15 Jul 2022 14:01:32 +0200 Subject: [PATCH 65/71] feat: add lifetimes exercises --- exercises/lifetimes/README.md | 17 +++++++++++++++++ exercises/lifetimes/lifetimes1.rs | 26 ++++++++++++++++++++++++++ exercises/lifetimes/lifetimes2.rs | 27 +++++++++++++++++++++++++++ exercises/lifetimes/lifetimes3.rs | 20 ++++++++++++++++++++ info.toml | 24 ++++++++++++++++++++++++ 5 files changed, 114 insertions(+) create mode 100644 exercises/lifetimes/README.md create mode 100644 exercises/lifetimes/lifetimes1.rs create mode 100644 exercises/lifetimes/lifetimes2.rs create mode 100644 exercises/lifetimes/lifetimes3.rs diff --git a/exercises/lifetimes/README.md b/exercises/lifetimes/README.md new file mode 100644 index 00000000..72befb3e --- /dev/null +++ b/exercises/lifetimes/README.md @@ -0,0 +1,17 @@ +# Lifetimes + +Lifetimes tell the compiler how to check whether references live long +enough to be valid in any given situation. For example lifetimes say +"make sure parameter 'a' lives as long as parameter 'b' so that the return +value is valid". + +They are only necessary on borrows, i.e. references, +since copied parameters or moves are owned in their scope and cannot +be referenced outside. Lifetimes mean that calling code of e.g. functions +can be checked to make sure their arguments are valid. Lifetimes are +restrictive of their callers. + +## Further information + +- [Validating References with Lifetimes](https://doc.rust-lang.org/book/ch10-03-lifetime-syntax.html) +- [Lifetimes (in Rust By Example)](https://doc.rust-lang.org/stable/rust-by-example/scope/lifetime.html) diff --git a/exercises/lifetimes/lifetimes1.rs b/exercises/lifetimes/lifetimes1.rs new file mode 100644 index 00000000..58e995c6 --- /dev/null +++ b/exercises/lifetimes/lifetimes1.rs @@ -0,0 +1,26 @@ +// lifetimes1.rs +// +// The Rust compiler needs to know how to check whether supplied references are +// valid, so that it can let the programmer know if a reference is at risk +// of going out of scope before it is used. Remember, references are borrows +// and do not own their own data. What if their owner goes out of scope? +// +// Execute `rustlings hint lifetimes1` or use the `hint` watch subcommand for a hint. + +// I AM NOT DONE + +fn longest(x: &str, y: &str) -> &str { + if x.len() > y.len() { + x + } else { + y + } +} + +fn main() { + let string1 = String::from("abcd"); + let string2 = "xyz"; + + let result = longest(string1.as_str(), string2); + println!("The longest string is {}", result); +} diff --git a/exercises/lifetimes/lifetimes2.rs b/exercises/lifetimes/lifetimes2.rs new file mode 100644 index 00000000..c73a28ad --- /dev/null +++ b/exercises/lifetimes/lifetimes2.rs @@ -0,0 +1,27 @@ +// lifetimes2.rs +// +// So if the compiler is just validating the references passed +// to the annotated parameters and the return type, what do +// we need to change? +// +// Execute `rustlings hint lifetimes2` or use the `hint` watch subcommand for a hint. + +// I AM NOT DONE + +fn longest<'a>(x: &'a str, y: &'a str) -> &'a str { + if x.len() > y.len() { + x + } else { + y + } +} + +fn main() { + let string1 = String::from("long string is long"); + let result; + { + let string2 = String::from("xyz"); + result = longest(string1.as_str(), string2.as_str()); + } + println!("The longest string is {}", result); +} diff --git a/exercises/lifetimes/lifetimes3.rs b/exercises/lifetimes/lifetimes3.rs new file mode 100644 index 00000000..ea483708 --- /dev/null +++ b/exercises/lifetimes/lifetimes3.rs @@ -0,0 +1,20 @@ +// lifetimes3.rs +// +// Lifetimes are also needed when structs hold references. +// +// Execute `rustlings hint lifetimes3` or use the `hint` watch subcommand for a hint. + +// I AM NOT DONE + +struct Book { + author: &str, + title: &str, +} + +fn main() { + let name = String::from("Jill Smith"); + let title = String::from("Fish Flying"); + let book = Book { author: &name, title: &title }; + + println!("{} by {}", book.title, book.author); +} diff --git a/info.toml b/info.toml index 8871c15b..bc2a91c9 100644 --- a/info.toml +++ b/info.toml @@ -746,6 +746,30 @@ You can call a function right where you're passing arguments to `assert!` -- so something like `assert!(having_fun())`. If you want to check that you indeed get false, you can negate the result of what you're doing using `!`, like `assert!(!having_fun())`.""" +# LIFETIMES + +[[exercises]] +name = "lifetimes1" +path = "exercises/lifetimes/lifetimes1.rs" +mode = "compile" +hint = """ +Let the compiler guide you. Also take a look at the book if you need help: +https://doc.rust-lang.org/book/ch10-03-lifetime-syntax.html""" + +[[exercises]] +name = "lifetimes2" +path = "exercises/lifetimes/lifetimes2.rs" +mode = "compile" +hint = """ +What is the compiler checking? How could you change how long an owned variable lives?""" + +[[exercises]] +name = "lifetimes3" +path = "exercises/lifetimes/lifetimes3.rs" +mode = "compile" +hint = """ +If you use a lifetime annotation in a struct's fields, where else does it need to be added?""" + # STANDARD LIBRARY TYPES [[exercises]] From 9b66b2a0e981269c0b22e3b5b4057fb4c45fbba1 Mon Sep 17 00:00:00 2001 From: Rod Elias Date: Fri, 15 Jul 2022 14:08:51 +0200 Subject: [PATCH 66/71] fix(try_from_into): fix function name --- exercises/conversions/try_from_into.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exercises/conversions/try_from_into.rs b/exercises/conversions/try_from_into.rs index bc71a3c3..fa98bc90 100644 --- a/exercises/conversions/try_from_into.rs +++ b/exercises/conversions/try_from_into.rs @@ -56,7 +56,7 @@ impl TryFrom<&[i16]> for Color { } fn main() { - // Use the `from` function + // Use the `try_from` function let c1 = Color::try_from((183, 65, 14)); println!("{:?}", c1); From f43c6d78770ac90725490344dad98b9d3c076484 Mon Sep 17 00:00:00 2001 From: Sam White Date: Fri, 25 Feb 2022 16:40:38 +0000 Subject: [PATCH 67/71] feat: Add traits3.rs exercise --- exercises/traits/traits3.rs | 40 +++++++++++++++++++++++++++++++++++++ info.toml | 12 +++++++++++ 2 files changed, 52 insertions(+) create mode 100644 exercises/traits/traits3.rs diff --git a/exercises/traits/traits3.rs b/exercises/traits/traits3.rs new file mode 100644 index 00000000..917ded70 --- /dev/null +++ b/exercises/traits/traits3.rs @@ -0,0 +1,40 @@ +// traits3.rs +// +// Your task is to implement the Licensed trait for +// both structures and have them return the same +// information without writing the same function twice. +// +// Consider what you can add to the Licensed trait. + +// I AM NOT DONE + +pub trait Licensed { + fn licensing_info(&self) -> String; +} + +struct SomeSoftware { + version_number: i32, +} + +struct OtherSoftware { + version_number: String, +} + +impl Licensed for SomeSoftware {} // Don't edit this line +impl Licensed for OtherSoftware {} // Don't edit this line + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn is_licensing_info_the_same() { + let licensing_info = String::from("Some information"); + let some_software = SomeSoftware { version_number: 1 }; + let other_software = OtherSoftware { + version_number: "v2.0.0".to_string(), + }; + assert_eq!(some_software.licensing_info(), licensing_info); + assert_eq!(other_software.licensing_info(), licensing_info); + } +} diff --git a/info.toml b/info.toml index bc2a91c9..971f5155 100644 --- a/info.toml +++ b/info.toml @@ -704,6 +704,18 @@ what the result should look like! Vectors provide suitable methods for adding an element at the end. See the documentation at: https://doc.rust-lang.org/std/vec/struct.Vec.html""" +[[exercises]] +name = "traits3" +path = "exercises/traits/traits3.rs" +mode = "test" +hint = """ +Traits can have a default implementation for functions. Structs that implement +the trait can then use the default version of these functions if they choose not +implement the function themselves. + +See the documentation at: https://doc.rust-lang.org/book/ch10-02-traits.html#default-implementations +""" + # QUIZ 3 [[exercises]] From 599d634ee2277d1071dd803346993c24ab13462b Mon Sep 17 00:00:00 2001 From: Sam White Date: Fri, 25 Feb 2022 16:41:10 +0000 Subject: [PATCH 68/71] feat: Add traits4.rs exercise --- exercises/traits/traits4.rs | 44 +++++++++++++++++++++++++++++++++++++ info.toml | 11 ++++++++++ 2 files changed, 55 insertions(+) create mode 100644 exercises/traits/traits4.rs diff --git a/exercises/traits/traits4.rs b/exercises/traits/traits4.rs new file mode 100644 index 00000000..cc5fe168 --- /dev/null +++ b/exercises/traits/traits4.rs @@ -0,0 +1,44 @@ +// traits4.rs +// +// Your task is to replace the '??' sections so the code compiles. +// Don't change any line other than 21. + +// I AM NOT DONE + +pub trait Licensed { + fn licensing_info(&self) -> String { + "some information".to_string() + } +} + +struct SomeSoftware {} + +struct OtherSoftware {} + +impl Licensed for SomeSoftware {} +impl Licensed for OtherSoftware {} + +fn compare_license_types(software: ??, software_two: ??) -> bool { + software.licensing_info() == software_two.licensing_info() +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn compare_license_information() { + let some_software = SomeSoftware {}; + let other_software = OtherSoftware {}; + + assert!(compare_license_types(some_software, other_software)); + } + + #[test] + fn compare_license_information_backwards() { + let some_software = SomeSoftware {}; + let other_software = OtherSoftware {}; + + assert!(compare_license_types(other_software, some_software)); + } +} diff --git a/info.toml b/info.toml index 971f5155..2ad9a0eb 100644 --- a/info.toml +++ b/info.toml @@ -716,6 +716,17 @@ implement the function themselves. See the documentation at: https://doc.rust-lang.org/book/ch10-02-traits.html#default-implementations """ +[[exercises]] +name = "traits4" +path = "exercises/traits/traits4.rs" +mode = "test" +hint = """ +Instead of using concrete types as parameters you can use traits. Try replacing the +'??' with 'impl ' + +See the documentation at: https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters +""" + # QUIZ 3 [[exercises]] From 63b0c7e399ad11246bf5bf3acac4517f67c890da Mon Sep 17 00:00:00 2001 From: Sam White Date: Fri, 25 Feb 2022 16:41:36 +0000 Subject: [PATCH 69/71] feat: add traits5.rs exercise --- exercises/traits/traits5.rs | 31 +++++++++++++++++++++++++++++++ info.toml | 11 +++++++++++ 2 files changed, 42 insertions(+) create mode 100644 exercises/traits/traits5.rs diff --git a/exercises/traits/traits5.rs b/exercises/traits/traits5.rs new file mode 100644 index 00000000..ed2afb1e --- /dev/null +++ b/exercises/traits/traits5.rs @@ -0,0 +1,31 @@ +// traits5.rs +// +// Your task is to replace the '??' sections so the code compiles. +// Don't change any line other than 27. + +// I AM NOT DONE + +pub trait SomeTrait { + fn some_function(&self) -> bool { + true + } +} + +pub trait OtherTrait { + fn other_function(&self) -> bool { + true + } +} + +struct SomeStruct { + name: String, +} + +impl SomeTrait for SomeStruct {} +impl OtherTrait for SomeStruct {} + +fn some_func(item: ??) -> bool { + item.some_function() && item.other_function() +} + +fn main() {} diff --git a/info.toml b/info.toml index 2ad9a0eb..5b7b9b43 100644 --- a/info.toml +++ b/info.toml @@ -727,6 +727,17 @@ Instead of using concrete types as parameters you can use traits. Try replacing See the documentation at: https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters """ +[[exercises]] +name = "traits5" +path = "exercises/traits/traits5.rs" +mode = "compile" +hint = """ +To ensure a paramter implements multiple traits use the '+ syntax'. Try replacing the +'??' with 'impl <> + <>'. + +See the documentation at: https://doc.rust-lang.org/book/ch10-02-traits.html#specifying-multiple-trait-bounds-with-the--syntax +""" + # QUIZ 3 [[exercises]] From 1a7a3f5c8e4544873d25ec5338dbdf366aba9f8a Mon Sep 17 00:00:00 2001 From: mokou Date: Fri, 15 Jul 2022 14:14:48 +0200 Subject: [PATCH 70/71] fix(traits): update hint comments --- exercises/traits/traits3.rs | 1 + exercises/traits/traits4.rs | 1 + exercises/traits/traits5.rs | 1 + 3 files changed, 3 insertions(+) diff --git a/exercises/traits/traits3.rs b/exercises/traits/traits3.rs index 917ded70..6d2fd6c3 100644 --- a/exercises/traits/traits3.rs +++ b/exercises/traits/traits3.rs @@ -5,6 +5,7 @@ // information without writing the same function twice. // // Consider what you can add to the Licensed trait. +// Execute `rustlings hint traits3` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/exercises/traits/traits4.rs b/exercises/traits/traits4.rs index cc5fe168..280aaade 100644 --- a/exercises/traits/traits4.rs +++ b/exercises/traits/traits4.rs @@ -2,6 +2,7 @@ // // Your task is to replace the '??' sections so the code compiles. // Don't change any line other than 21. +// Execute `rustlings hint traits4` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/exercises/traits/traits5.rs b/exercises/traits/traits5.rs index ed2afb1e..290c0479 100644 --- a/exercises/traits/traits5.rs +++ b/exercises/traits/traits5.rs @@ -2,6 +2,7 @@ // // Your task is to replace the '??' sections so the code compiles. // Don't change any line other than 27. +// Execute `rustlings hint traits5` or use the `hint` watch subcommand for a hint. // I AM NOT DONE From c265b681b188ea21b3f8585e65ea363fc02c4b50 Mon Sep 17 00:00:00 2001 From: Neil Pate Date: Fri, 15 Jul 2022 14:18:31 +0200 Subject: [PATCH 71/71] fix(quiz1): change function name --- exercises/quiz1.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/exercises/quiz1.rs b/exercises/quiz1.rs index 7bd3f589..8d05b110 100644 --- a/exercises/quiz1.rs +++ b/exercises/quiz1.rs @@ -11,14 +11,14 @@ // I AM NOT DONE // Put your function here! -// fn calculate_apple_price { +// fn calculate_price_of_apples { // Don't modify this function! #[test] fn verify_test() { - let price1 = calculate_apple_price(35); - let price2 = calculate_apple_price(40); - let price3 = calculate_apple_price(65); + let price1 = calculate_price_of_apples(35); + let price2 = calculate_price_of_apples(40); + let price3 = calculate_price_of_apples(65); assert_eq!(70, price1); assert_eq!(80, price2);