diff --git a/Cargo.lock b/Cargo.lock index 0a61ec78e9..060acb9cf1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -600,7 +600,7 @@ dependencies = [ [[package]] name = "rustlings" -version = "1.4.1" +version = "1.5.0" dependencies = [ "assert_cmd 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)", "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/exercises/enums/enums1.rs b/exercises/enums/enums1.rs index 8b14f29c5d..fa0f1bd1d9 100644 --- a/exercises/enums/enums1.rs +++ b/exercises/enums/enums1.rs @@ -3,7 +3,10 @@ #[derive(Debug)] enum Message { - // TODO: define a few types of messages as used below + Quit, + Echo, + Move, + ChangeColor, } fn main() { @@ -13,30 +16,4 @@ fn main() { println!("{:?}", Message::ChangeColor); } - - - - - - - - - - - - - - - - - - - - - - - - - - // Hint: The declaration of the enumeration type has not been defined yet. diff --git a/exercises/enums/enums2.rs b/exercises/enums/enums2.rs index 71ac839757..e306771272 100644 --- a/exercises/enums/enums2.rs +++ b/exercises/enums/enums2.rs @@ -3,7 +3,10 @@ #[derive(Debug)] enum Message { - // TODO: define the different variants used below + Move { x: i32, y: i32 }, + Echo(String), + ChangeColor(i32, i32, i32), + Quit, } impl Message { @@ -14,10 +17,10 @@ impl Message { fn main() { let messages = [ - Message::Move{ x: 10, y: 30 }, + Message::Move { x: 10, y: 30 }, Message::Echo(String::from("hello world")), Message::ChangeColor(200, 255, 255), - Message::Quit + Message::Quit, ]; for message in &messages { @@ -25,37 +28,5 @@ fn main() { } } - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Hint: you can create enumerations that have different variants with different types // such as no data, anonymous structs, a single string, tuples, ...etc diff --git a/exercises/enums/enums3.rs b/exercises/enums/enums3.rs index c5d81bf90b..d70e32eac8 100644 --- a/exercises/enums/enums3.rs +++ b/exercises/enums/enums3.rs @@ -3,17 +3,21 @@ enum Message { // TODO: implement the message variant types based on their usage below + Move { x: u8, y: u8 }, + Echo(String), + ChangeColor(u8, u8, u8), + Quit, } struct Point { x: u8, - y: u8 + y: u8, } struct State { color: (u8, u8, u8), position: Point, - quit: bool + quit: bool, } impl State { @@ -35,6 +39,12 @@ impl State { fn process(&mut self, message: Message) { // TODO: create a match expression to process the different message variants + match message { + Message::ChangeColor(r, g, b) => self.change_color((r, g, b)), + Message::Echo(s) => self.echo(s), + Message::Move { x: x, y: y } => self.move_position(Point { x, y }), + Message::Quit => self.quit(), + } } } @@ -44,14 +54,14 @@ mod tests { #[test] fn test_match_message_call() { - let mut state = State{ + let mut state = State { quit: false, - position: Point{ x: 0, y: 0 }, - color: (0, 0, 0) + position: Point { x: 0, y: 0 }, + color: (0, 0, 0), }; state.process(Message::ChangeColor(255, 0, 255)); state.process(Message::Echo(String::from("hello world"))); - state.process(Message::Move{ x: 10, y: 15 }); + state.process(Message::Move { x: 10, y: 15 }); state.process(Message::Quit); assert_eq!(state.color, (255, 0, 255)); @@ -59,5 +69,4 @@ mod tests { assert_eq!(state.position.y, 15); assert_eq!(state.quit, true); } - } diff --git a/exercises/error_handling/errors1.rs b/exercises/error_handling/errors1.rs index 848323492f..d89699de98 100644 --- a/exercises/error_handling/errors1.rs +++ b/exercises/error_handling/errors1.rs @@ -6,12 +6,12 @@ // this function to have. // Scroll down for hints!!! -pub fn generate_nametag_text(name: String) -> Option { +pub fn generate_nametag_text(name: String) -> Result { if name.len() > 0 { - Some(format!("Hi! My name is {}", name)) + Ok(format!("Hi! My name is {}", name)) } else { // Empty names aren't allowed. - None + Err(String::from("`name` was empty; it must be nonempty.")) } } @@ -26,7 +26,7 @@ mod tests { fn generates_nametag_text_for_a_nonempty_name() { assert_eq!( generate_nametag_text("Beyoncé".into()), - Some("Hi! My name is Beyoncé".into()) + Ok("Hi! My name is Beyoncé".into()) ); } @@ -39,25 +39,6 @@ mod tests { } } - - - - - - - - - - - - - - - - - - - // `Err` is one of the variants of `Result`, so what the 2nd test is saying // is that `generate_nametag_text` should return a `Result` instead of an // `Option`. diff --git a/exercises/error_handling/errors2.rs b/exercises/error_handling/errors2.rs index 8b81207e33..3d583aab0c 100644 --- a/exercises/error_handling/errors2.rs +++ b/exercises/error_handling/errors2.rs @@ -21,8 +21,13 @@ use std::num::ParseIntError; pub fn total_cost(item_quantity: &str) -> Result { let processing_fee = 1; let cost_per_item = 5; - let qty = item_quantity.parse::(); + // match item_quantity.parse::() { + // Ok(qty) => Ok(qty * cost_per_item + processing_fee), + // Err(e) => Err(e), + // } + // this does the same thing as the match statement above + let qty = item_quantity.parse::()?; Ok(qty * cost_per_item + processing_fee) } @@ -44,22 +49,6 @@ mod tests { } } - - - - - - - - - - - - - - - - // One way to handle this is using a `match` statement on // `item_quantity.parse::()` where the cases are `Ok(something)` and // `Err(something)`. This pattern is very common in Rust, though, so there's diff --git a/exercises/error_handling/errors3.rs b/exercises/error_handling/errors3.rs index 9c29af587f..7f8d91a038 100644 --- a/exercises/error_handling/errors3.rs +++ b/exercises/error_handling/errors3.rs @@ -10,7 +10,7 @@ fn main() { let mut tokens = 100; let pretend_user_input = "8"; - let cost = total_cost(pretend_user_input)?; + let cost = total_cost(pretend_user_input).unwrap(); if cost > tokens { println!("You can't afford that many!"); @@ -28,23 +28,6 @@ pub fn total_cost(item_quantity: &str) -> Result { Ok(qty * cost_per_item + processing_fee) } - - - - - - - - - - - - - - - - - // Since the `?` operator returns an `Err` early if the thing it's trying to // do fails, you can only use the `?` operator in functions that have a // `Result` as their return type. diff --git a/exercises/error_handling/errorsn.rs b/exercises/error_handling/errorsn.rs index c2b16ce36b..d95da973b9 100644 --- a/exercises/error_handling/errorsn.rs +++ b/exercises/error_handling/errorsn.rs @@ -20,12 +20,14 @@ use std::fmt; use std::io; // PositiveNonzeroInteger is a struct defined below the tests. -fn read_and_validate(b: &mut dyn io::BufRead) -> Result { +fn read_and_validate( + b: &mut dyn io::BufRead, +) -> Result> { let mut line = String::new(); - b.read_line(&mut line); - let num: i64 = line.trim().parse(); - let answer = PositiveNonzeroInteger::new(num); - answer + b.read_line(&mut line)?; + let num: i64 = line.trim().parse()?; + let answer = PositiveNonzeroInteger::new(num)?; + Ok(answer) } // This is a test helper function that turns a &str into a BufReader. @@ -111,84 +113,16 @@ impl error::Error for CreationError { } } - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // First hint: To figure out what type should go where the ??? is, take a look // at the test helper function `test_with_str`, since it returns whatever // `read_and_validate` returns and`test_with_str` has its signature fully // specified. - - - - - - - - - - - - - - - - - - - // Next hint: There are three places in `read_and_validate` that we call a // function that returns a `Result` (that is, the functions might fail). // Apply the `?` operator on those calls so that we return immediately from // `read_and_validate` if those function calls fail. - - - - - - - - - - - - - - - - - - - // 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 @@ -197,50 +131,12 @@ impl error::Error for CreationError { // 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 - - - - - - - - - - - - - - - - - - - // Another another hint: Note that because the `?` operator returns // the *unwrapped* value in the `Ok` case, if we want to return a `Result` from // `read_and_validate` for *its* success case, we'll have to rewrap a value // that we got from the return value of a `?`ed call in an `Ok`-- this will // look like `Ok(something)`. - - - - - - - - - - - - - - - - - - - // Another another another hint: `Result`s must be "used", that is, you'll // get a warning if you don't handle a `Result` that you get in your // function. Read more about that in the `std::result` module docs: diff --git a/exercises/error_handling/option1.rs b/exercises/error_handling/option1.rs index c5a4a64d93..b78115c205 100644 --- a/exercises/error_handling/option1.rs +++ b/exercises/error_handling/option1.rs @@ -6,15 +6,15 @@ pub fn pop_too_much() -> bool { let mut list = vec![3]; + println!("list is {:?}", list); let last = list.pop().unwrap(); println!("The last item in the list is {:?}", last); - let second_to_last = list.pop().unwrap(); - println!( - "The second-to-last item in the list is {:?}", - second_to_last - ); + match list.pop() { + Some(num) => println!("The second-to-last item in the list is {:?}", num), + None => println!("No more elements!"), + } true } @@ -28,28 +28,6 @@ mod tests { } } - - - - - - - - - - - - - - - - - - - - - - // Try using a `match` statement where the arms are `Some(thing)` and `None`. // Or set a default value to print out if you get `None` by using the // function `unwrap_or`. diff --git a/exercises/error_handling/result1.rs b/exercises/error_handling/result1.rs index f9596e24bf..dac2ba2dc1 100644 --- a/exercises/error_handling/result1.rs +++ b/exercises/error_handling/result1.rs @@ -12,7 +12,13 @@ enum CreationError { impl PositiveNonzeroInteger { fn new(value: i64) -> Result { - Ok(PositiveNonzeroInteger(value as u64)) + if value < 0 { + Err(CreationError::Negative) + } else if value == 0 { + Err(CreationError::Zero) + } else { + Ok(PositiveNonzeroInteger(value as u64)) + } } } @@ -26,21 +32,6 @@ fn test_creation() { assert_eq!(Err(CreationError::Zero), PositiveNonzeroInteger::new(0)); } - - - - - - - - - - - - - - - // `PositiveNonzeroInteger::new` is always creating a new instance and returning an `Ok` result. // It should be doing some checking, returning an `Err` result if those checks fail, and only // returning an `Ok` result if those checks determine that everything is... okay :) diff --git a/exercises/functions/functions1.rs b/exercises/functions/functions1.rs index 396dd56f99..367c9cf31a 100644 --- a/exercises/functions/functions1.rs +++ b/exercises/functions/functions1.rs @@ -5,38 +5,7 @@ fn main() { call_me(); } - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +fn call_me() {} // This main function is calling a function that it expects to exist, but the // function doesn't exist. It expects this function to have the name `call_me`. diff --git a/exercises/functions/functions2.rs b/exercises/functions/functions2.rs index 1cf95c3242..8194cded18 100644 --- a/exercises/functions/functions2.rs +++ b/exercises/functions/functions2.rs @@ -5,38 +5,11 @@ fn main() { call_me(3); } -fn call_me(num) { +fn call_me(num: u32) { for i in 0..num { println!("Ring! Call number {}", i + 1); } } - - - - - - - - - - - - - - - - - - - - - - - - - - - // Rust requires that all parts of a function's signature have type annotations, // but `call_me` is missing the type annotation of `num`. diff --git a/exercises/functions/functions3.rs b/exercises/functions/functions3.rs index b17543b3e7..fa6869c469 100644 --- a/exercises/functions/functions3.rs +++ b/exercises/functions/functions3.rs @@ -2,7 +2,7 @@ // Make me compile! Scroll down for hints :) fn main() { - call_me(); + call_me(4); } fn call_me(num: i32) { @@ -11,32 +11,5 @@ fn call_me(num: i32) { } } - - - - - - - - - - - - - - - - - - - - - - - - - - - // This time, the function *declaration* is okay, but there's something wrong // with the place where we're calling the function. diff --git a/exercises/functions/functions4.rs b/exercises/functions/functions4.rs index 5baca0e625..d7b1ef11b5 100644 --- a/exercises/functions/functions4.rs +++ b/exercises/functions/functions4.rs @@ -9,7 +9,7 @@ fn main() { println!("Your sale price is {}", sale_price(original_price)); } -fn sale_price(price: i32) -> { +fn sale_price(price: i32) -> i32 { if is_even(price) { price - 10 } else { @@ -21,24 +21,6 @@ fn is_even(num: i32) -> bool { num % 2 == 0 } - - - - - - - - - - - - - - - - - - // The error message points to line 12 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! diff --git a/exercises/functions/functions5.rs b/exercises/functions/functions5.rs index d9227c9e5e..f1464cd405 100644 --- a/exercises/functions/functions5.rs +++ b/exercises/functions/functions5.rs @@ -7,37 +7,9 @@ fn main() { } fn square(num: i32) -> i32 { - num * num; + num * num } - - - - - - - - - - - - - - - - - - - - - - - - - - - - // This is a really common error that can be fixed by removing one character. // It happens because Rust distinguishes between expressions and statements: expressions return // a value based on its operand, and statements simply return a () type which behaves just like `void` in C/C++ language. diff --git a/exercises/if/if1.rs b/exercises/if/if1.rs index 636e6ce5d0..abe1e7f5b4 100644 --- a/exercises/if/if1.rs +++ b/exercises/if/if1.rs @@ -7,6 +7,11 @@ pub fn bigger(a: i32, b: i32) -> i32 { // - another function call // - additional variables // Scroll down for hints. + if a > b { + a + } else { + b + } } // Don't mind this for now :) @@ -25,30 +30,6 @@ mod tests { } } - - - - - - - - - - - - - - - - - - - - - - - - // It's possible to do this in one line if you would like! // Some similar examples from other languages: // - In C(++) this would be: `a > b ? a : b` diff --git a/exercises/macros/macros1.rs b/exercises/macros/macros1.rs index a7c78a57f4..ba388fd423 100644 --- a/exercises/macros/macros1.rs +++ b/exercises/macros/macros1.rs @@ -8,57 +8,9 @@ macro_rules! my_macro { } fn main() { - my_macro(); + my_macro!(); } - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // When you call a macro, you need to add something special compared to a // regular function call. If you're stuck, take a look at what's inside // `my_macro`. diff --git a/exercises/macros/macros2.rs b/exercises/macros/macros2.rs index bc2e56be4b..642543736c 100644 --- a/exercises/macros/macros2.rs +++ b/exercises/macros/macros2.rs @@ -1,73 +1,18 @@ // macros2.rs // Make me compile! Scroll down for hints :) -fn main() { - my_macro!(); -} - macro_rules! my_macro { () => { println!("Check out my macro!"); }; } - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +fn main() { + my_macro!(); +} // Macros don't quite play by the same rules as the rest of Rust, in terms of // what's available where. - - - - - - - // Unlike other things in Rust, the order of "where you define a macro" versus // "where you use it" actually matters. diff --git a/exercises/macros/macros3.rs b/exercises/macros/macros3.rs index 84c4308e23..17ba9c9d58 100644 --- a/exercises/macros/macros3.rs +++ b/exercises/macros/macros3.rs @@ -2,6 +2,7 @@ // Make me compile, without taking the macro out of the module! Scroll down for hints :) mod macros { + #[macro_export] macro_rules! my_macro { () => { println!("Check out my macro!"); @@ -13,63 +14,8 @@ fn main() { my_macro!(); } - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // In order to use a macro outside of its module, you need to do something // special to the module to lift the macro out into its parent. - - - - - - - // The same trick also works on "extern crate" statements for crates that have // exported macros, if you've seen any of those around. diff --git a/exercises/macros/macros4.rs b/exercises/macros/macros4.rs index d844bb0d9f..d16f022dd6 100644 --- a/exercises/macros/macros4.rs +++ b/exercises/macros/macros4.rs @@ -4,10 +4,10 @@ macro_rules! my_macro { () => { println!("Check out my macro!"); - } + }; ($val:expr) => { println!("Look at this other macro: {}", $val); - } + }; } fn main() { @@ -15,63 +15,7 @@ fn main() { my_macro!(7777); } - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // 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. diff --git a/exercises/modules/modules1.rs b/exercises/modules/modules1.rs index 0e092c5fc7..9697f639e4 100644 --- a/exercises/modules/modules1.rs +++ b/exercises/modules/modules1.rs @@ -2,7 +2,7 @@ // Make me compile! Scroll down for hints :) mod sausage_factory { - fn make_sausage() { + pub fn make_sausage() { println!("sausage!"); } } @@ -11,33 +11,6 @@ fn main() { sausage_factory::make_sausage(); } - - - - - - - - - - - - - - - - - - - - - - - - - - - // Everything is private in Rust by default-- but there's a keyword we can use // to make something public! The compiler error should point to the thing that // needs to be public. diff --git a/exercises/modules/modules2.rs b/exercises/modules/modules2.rs index 3cfa36db3c..0cae70c6e6 100644 --- a/exercises/modules/modules2.rs +++ b/exercises/modules/modules2.rs @@ -2,8 +2,8 @@ // Make me compile! Scroll down for hints :) mod delicious_snacks { - use self::fruits::PEAR as fruit; - use self::veggies::CUCUMBER as veggie; + pub use self::fruits::PEAR as fruit; + pub use self::veggies::CUCUMBER as veggie; mod fruits { pub const PEAR: &'static str = "Pear"; @@ -24,22 +24,6 @@ fn main() { ); } - - - - - - - - - - - - - - - - // The delicious_snacks module is trying to present an external // interface (the `fruit` and `veggie` constants) that is different than // its internal structure (the `fruits` and `veggies` modules and diff --git a/exercises/move_semantics/move_semantics1.rs b/exercises/move_semantics/move_semantics1.rs index ab855fca38..a286486dbc 100644 --- a/exercises/move_semantics/move_semantics1.rs +++ b/exercises/move_semantics/move_semantics1.rs @@ -4,7 +4,7 @@ fn main() { let vec0 = Vec::new(); - let vec1 = fill_vec(vec0); + let mut vec1 = fill_vec(vec0); println!("{} has length {} content `{:?}`", "vec1", vec1.len(), vec1); @@ -23,20 +23,6 @@ fn fill_vec(vec: Vec) -> Vec { vec } - - - - - - - - - - - - - - // So you've got the "cannot borrow immutable local variable `vec1` as mutable" error on line 11, // right? The fix for this is going to be adding one keyword, and the addition is NOT on line 11 // where the error is. diff --git a/exercises/move_semantics/move_semantics2.rs b/exercises/move_semantics/move_semantics2.rs index f85b3ed63a..f9cf30e0b0 100644 --- a/exercises/move_semantics/move_semantics2.rs +++ b/exercises/move_semantics/move_semantics2.rs @@ -2,41 +2,24 @@ // Make me compile without changing line 10! Scroll down for hints :) fn main() { - let vec0 = Vec::new(); + let mut vec0 = Vec::new(); - let mut vec1 = fill_vec(vec0); + fill_vec(&mut vec0); // Do not change the following line! println!("{} has length {} content `{:?}`", "vec0", vec0.len(), vec0); - vec1.push(88); + vec0.push(88); - println!("{} has length {} content `{:?}`", "vec1", vec1.len(), vec1); + println!("{} has length {} content `{:?}`", "vec0", vec0.len(), vec0); } -fn fill_vec(vec: Vec) -> Vec { - let mut vec = vec; - +fn fill_vec(vec: &mut Vec) { vec.push(22); vec.push(44); vec.push(66); - - vec } - - - - - - - - - - - - - // So `vec0` is being *moved* into the function `fill_vec` when we call it on // line 7, which means it gets dropped at the end of `fill_vec`, which means we // can't use `vec0` again on line 10 (or anywhere else in `main` after the diff --git a/exercises/move_semantics/move_semantics3.rs b/exercises/move_semantics/move_semantics3.rs index 8b918968f8..86d1278aa9 100644 --- a/exercises/move_semantics/move_semantics3.rs +++ b/exercises/move_semantics/move_semantics3.rs @@ -15,7 +15,7 @@ fn main() { println!("{} has length {} content `{:?}`", "vec1", vec1.len(), vec1); } -fn fill_vec(vec: Vec) -> Vec { +fn fill_vec(mut vec: Vec) -> Vec { vec.push(22); vec.push(44); vec.push(66); @@ -23,22 +23,6 @@ fn fill_vec(vec: Vec) -> Vec { vec } - - - - - - - - - - - - - - - - // The difference between this one and the previous ones is that the first line // of `fn fill_vec` that had `let mut vec = vec;` is no longer there. You can, // instead of adding that line back, add `mut` in one place that will change diff --git a/exercises/move_semantics/move_semantics4.rs b/exercises/move_semantics/move_semantics4.rs index 90930f0f47..be441510d9 100644 --- a/exercises/move_semantics/move_semantics4.rs +++ b/exercises/move_semantics/move_semantics4.rs @@ -4,9 +4,7 @@ // freshly created vector from fill_vec to its caller. Scroll for hints! fn main() { - let vec0 = Vec::new(); - - let mut vec1 = fill_vec(vec0); + let mut vec1 = fill_vec(); println!("{} has length {} content `{:?}`", "vec1", vec1.len(), vec1); @@ -17,7 +15,7 @@ fn main() { // `fill_vec()` no longer take `vec: Vec` as argument fn fill_vec() -> Vec { - let mut vec = vec; + let mut vec = vec![]; vec.push(22); vec.push(44); @@ -26,17 +24,6 @@ fn fill_vec() -> Vec { vec } - - - - - - - - - - - // Stop reading whenever you feel like you have enough direction :) Or try // doing one step and then fixing the compiler errors that result! // So the end goal is to: diff --git a/exercises/primitive_types/primitive_types1.rs b/exercises/primitive_types/primitive_types1.rs index c3d11fe8d3..91734c6914 100644 --- a/exercises/primitive_types/primitive_types1.rs +++ b/exercises/primitive_types/primitive_types1.rs @@ -10,7 +10,7 @@ fn main() { println!("Good morning!"); } - let // Finish the rest of this line like the example! Or make it be false! + let is_evening = false; // Finish the rest of this line like the example! Or make it be false! if is_evening { println!("Good evening!"); } diff --git a/exercises/primitive_types/primitive_types2.rs b/exercises/primitive_types/primitive_types2.rs index f5c8f87a43..6dec5ae5f0 100644 --- a/exercises/primitive_types/primitive_types2.rs +++ b/exercises/primitive_types/primitive_types2.rs @@ -14,9 +14,9 @@ fn main() { println!("Neither alphabetic nor numeric!"); } - let // Finish this line like the example! What's your favorite character? - // Try a letter, try a number, try a special character, try a character - // from a different language than your own, try an emoji! + let your_character = '旧'; // Finish this line like the example! What's your favorite character? + // Try a letter, try a number, try a special character, try a character + // from a different language than your own, try an emoji! if your_character.is_alphabetic() { println!("Alphabetical!"); } else if your_character.is_numeric() { diff --git a/exercises/primitive_types/primitive_types3.rs b/exercises/primitive_types/primitive_types3.rs index 7ce2226277..961a53fd88 100644 --- a/exercises/primitive_types/primitive_types3.rs +++ b/exercises/primitive_types/primitive_types3.rs @@ -1,9 +1,9 @@ // primitive_types3.rs -// Create an array with at least 100 elements in it where the ??? is. +// Create an array with at least 100 elements in it where the ??? is. // Scroll down for hints! fn main() { - let a = ??? + let a = ["hi"; 1000]; if a.len() >= 100 { println!("Wow, that's a big array!"); @@ -12,33 +12,7 @@ fn main() { } } - - - - - - - - - - - - - - - - - - - - - - - - - - -// There's a shorthand to initialize Arrays with a certain size that does not +// 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]; diff --git a/exercises/primitive_types/primitive_types4.rs b/exercises/primitive_types/primitive_types4.rs index e1ccdbcc4b..12ca56dd38 100644 --- a/exercises/primitive_types/primitive_types4.rs +++ b/exercises/primitive_types/primitive_types4.rs @@ -6,57 +6,11 @@ fn main() { let a = [1, 2, 3, 4, 5]; - let nice_slice = ??? + let nice_slice = &a[1..4]; assert_eq!([2, 3, 4], nice_slice) } - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // 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 diff --git a/exercises/primitive_types/primitive_types5.rs b/exercises/primitive_types/primitive_types5.rs index 0d53c9cb9d..aa5fd9e4d9 100644 --- a/exercises/primitive_types/primitive_types5.rs +++ b/exercises/primitive_types/primitive_types5.rs @@ -4,40 +4,11 @@ fn main() { let cat = ("Furry McFurson", 3.5); - let /* your pattern here */ = cat; + let (name, age) = cat; println!("{} is {} years old.", name, age); } - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // 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). diff --git a/exercises/primitive_types/primitive_types6.rs b/exercises/primitive_types/primitive_types6.rs index 854544fe24..2ad3b00350 100644 --- a/exercises/primitive_types/primitive_types6.rs +++ b/exercises/primitive_types/primitive_types6.rs @@ -5,39 +5,9 @@ fn main() { let numbers = (1, 2, 3); - println!("The second number is {}", ???); + println!("The second number is {}", numbers.1); } - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // 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: diff --git a/exercises/strings/strings1.rs b/exercises/strings/strings1.rs index 2e5088f90a..22e125269e 100644 --- a/exercises/strings/strings1.rs +++ b/exercises/strings/strings1.rs @@ -7,37 +7,9 @@ fn main() { } fn current_favorite_color() -> String { - "blue" + String::from("blue") } - - - - - - - - - - - - - - - - - - - - - - - - - - - - // 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 diff --git a/exercises/strings/strings2.rs b/exercises/strings/strings2.rs index c77e16fe81..e68ef8b727 100644 --- a/exercises/strings/strings2.rs +++ b/exercises/strings/strings2.rs @@ -3,7 +3,7 @@ fn main() { let word = String::from("green"); // Try not changing this line :) - if is_a_color_word(word) { + if is_a_color_word(&word) { println!("That is a color word I know!"); } else { println!("That is not a color word I know."); @@ -14,31 +14,6 @@ fn is_a_color_word(attempt: &str) -> bool { attempt == "green" || attempt == "blue" || attempt == "red" } - - - - - - - - - - - - - - - - - - - - - - - - - // 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 // 6, though, that will coerce the `String` into a string slice. diff --git a/exercises/structs/structs1.rs b/exercises/structs/structs1.rs index 870236df88..bd578620d3 100644 --- a/exercises/structs/structs1.rs +++ b/exercises/structs/structs1.rs @@ -2,10 +2,11 @@ // Address all the TODOs to make the tests pass! struct ColorClassicStruct { - // TODO: Something goes here + name: String, + hex: String, } -struct ColorTupleStruct(/* TODO: Something goes here */); +struct ColorTupleStruct(String, String); #[derive(Debug)] struct UnitStruct; @@ -17,7 +18,10 @@ mod tests { #[test] fn classic_c_structs() { // TODO: Instantiate a classic c struct! - // let green = + let green = ColorClassicStruct { + name: String::from("green"), + hex: String::from("#00FF00"), + }; assert_eq!(green.name, "green"); assert_eq!(green.hex, "#00FF00"); @@ -27,7 +31,7 @@ mod tests { fn tuple_structs() { // TODO: Instantiate a tuple struct! // For more fun, use the field initialization shorthand. - // let green = + let green = ColorTupleStruct(String::from("green"), String::from("#00FF00")); assert_eq!(green.0, "green"); assert_eq!(green.1, "#00FF00"); @@ -36,7 +40,7 @@ mod tests { #[test] fn unit_structs() { // TODO: Instantiate a unit struct! - // let unit_struct = + let unit_struct = UnitStruct {}; let message = format!("{:?}s are fun!", unit_struct); assert_eq!(message, "UnitStructs are fun!"); diff --git a/exercises/structs/structs2.rs b/exercises/structs/structs2.rs index db381e7b55..c63dfb07cc 100644 --- a/exercises/structs/structs2.rs +++ b/exercises/structs/structs2.rs @@ -33,7 +33,11 @@ mod tests { fn your_order() { let order_template = create_order_template(); // TODO: Create your own order using the update syntax and template above! - // let your_order = + let your_order = Order { + name: String::from("Hacker in Rust"), + count: 1, + ..order_template + }; assert_eq!(your_order.name, "Hacker in Rust"); assert_eq!(your_order.year, order_template.year); assert_eq!(your_order.made_by_phone, order_template.made_by_phone); diff --git a/exercises/test1.rs b/exercises/test1.rs index 6c27355f04..66d680bfbf 100644 --- a/exercises/test1.rs +++ b/exercises/test1.rs @@ -8,7 +8,13 @@ // the price of an order of apples given the order amount. No hints this time! // Put your function here! -// fn ..... { +fn calculate_apple_price(n: u32) -> u32 { + if n > 40 { + n + } else { + n * 2 + } +} // Don't modify this function! #[test] diff --git a/exercises/test2.rs b/exercises/test2.rs index 75a47391a2..63d165e697 100644 --- a/exercises/test2.rs +++ b/exercises/test2.rs @@ -17,11 +17,12 @@ mod tests { #[test] fn returns_twice_of_positive_numbers() { - assert_eq!(times_two(4), ???); + assert_eq!(times_two(4), 8); } #[test] fn returns_twice_of_negative_numbers() { // TODO write an assert for `times_two(-4)` + assert_eq!(times_two(-4), -8); } } diff --git a/exercises/test3.rs b/exercises/test3.rs index c8a5578789..9a3d644e1e 100644 --- a/exercises/test3.rs +++ b/exercises/test3.rs @@ -15,14 +15,14 @@ fn string(arg: String) { } 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()); + string_slice("blue"); + string("red".to_string()); + string(String::from("hi")); + string("rust is fun!".to_owned()); + string("nice weather".into()); + string(format!("Interpolation {}", "Station")); + string_slice(&String::from("abc")[0..1]); + string_slice(" hello there ".trim()); + string("Happy Monday!".to_string().replace("Mon", "Tues")); + string("mY sHiFt KeY iS sTiCkY".to_lowercase()); } diff --git a/exercises/test4.rs b/exercises/test4.rs index e50f1b0861..e3bcab8548 100644 --- a/exercises/test4.rs +++ b/exercises/test4.rs @@ -4,6 +4,11 @@ // - Macros // Write a macro that passes the test! No hints this time, you can do it! +macro_rules! my_macro { + ($val:expr) => { + $val + }; +} fn main() { if my_macro!("world!") != "Hello world!" { diff --git a/exercises/tests/tests1.rs b/exercises/tests/tests1.rs index b11221fd17..7908665665 100644 --- a/exercises/tests/tests1.rs +++ b/exercises/tests/tests1.rs @@ -10,38 +10,10 @@ mod tests { #[test] fn you_can_assert() { - assert!(); + assert!(true); } } - - - - - - - - - - - - - - - - - - - - - - - - - - - - // You don't even need to write any code to test -- you can just test values and run that, even // though you wouldn't do that in real life :) `assert!` is a macro that needs an argument. // Depending on the value of the argument, `assert!` will do nothing (in which case the test will diff --git a/exercises/tests/tests2.rs b/exercises/tests/tests2.rs index 6775d61041..c5d302a681 100644 --- a/exercises/tests/tests2.rs +++ b/exercises/tests/tests2.rs @@ -6,38 +6,10 @@ mod tests { #[test] fn you_can_assert_eq() { - assert_eq!(); + assert_eq!(1, 1); } } - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Like the previous exercise, you don't need to write any code to get this test to compile and // run. `assert_eq!` is a macro that takes two arguments and compares them. Try giving it two // values that are equal! Try giving it two arguments that are different! Try giving it two values diff --git a/exercises/tests/tests3.rs b/exercises/tests/tests3.rs index e10d2aaa32..1eb617a9c6 100644 --- a/exercises/tests/tests3.rs +++ b/exercises/tests/tests3.rs @@ -13,31 +13,11 @@ mod tests { #[test] fn is_true_when_even() { - assert!(); + assert!(is_even(4)); + assert!(!is_even(5)); } } - - - - - - - - - - - - - - - - - - - - - // You can call a function right where you're passing arguments to `assert!` -- so you could do // 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())`. diff --git a/exercises/threads/threads1.rs b/exercises/threads/threads1.rs index 7983668ae9..78e8ba9d6c 100644 --- a/exercises/threads/threads1.rs +++ b/exercises/threads/threads1.rs @@ -5,7 +5,7 @@ // of "waiting..." and the program ends without timing out the playground, // you've got it :) -use std::sync::Arc; +use std::sync::{Arc, Mutex}; use std::thread; use std::time::Duration; @@ -14,33 +14,21 @@ struct JobStatus { } fn main() { - let status = Arc::new(JobStatus { jobs_completed: 0 }); - let status_shared = status.clone(); + let status = Arc::new(Mutex::new(JobStatus { jobs_completed: 0 })); + let status_shared = Arc::clone(&status); thread::spawn(move || { for _ in 0..10 { thread::sleep(Duration::from_millis(250)); - status_shared.jobs_completed += 1; + let mut job_status = status_shared.lock().unwrap(); + job_status.jobs_completed += 1; } }); - while status.jobs_completed < 10 { + while status.lock().unwrap().jobs_completed < 10 { println!("waiting... "); thread::sleep(Duration::from_millis(500)); } } - - - - - - - - - - - - - // `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 @@ -48,32 +36,12 @@ fn main() { // https://doc.rust-lang.org/book/ch16-03-shared-state.html#atomic-reference-counting-with-arct // and keep scrolling if you'd like more hints :) - - - - - - - - - // Do you now have an `Arc` `Mutex` `JobStatus` at the beginning of main? Like: // `let status = Arc::new(Mutex::new(JobStatus { jobs_completed: 0 }));` // Similar to the code in the example in the book that happens after the text // that says "We can use Arc to fix this.". If not, give that a try! If you // do and would like more hints, keep scrolling!! - - - - - - - - - - - // Make sure neither of your threads are holding onto the lock of the mutex // while they are sleeping, since this will prevent the other thread from // being allowed to get the lock. Locks are automatically released when diff --git a/exercises/variables/variables1.rs b/exercises/variables/variables1.rs index 1cdd270271..9e2847a83d 100644 --- a/exercises/variables/variables1.rs +++ b/exercises/variables/variables1.rs @@ -2,41 +2,9 @@ // Make me compile! Scroll down for hints :) fn main() { - x = 5; + let x = 5; println!("x has the value {}", x); } - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Hint: The declaration on line 5 is missing a keyword that is needed in Rust // to create a new variable binding. diff --git a/exercises/variables/variables2.rs b/exercises/variables/variables2.rs index a0b4a37665..833b4c0d31 100644 --- a/exercises/variables/variables2.rs +++ b/exercises/variables/variables2.rs @@ -2,7 +2,7 @@ // Make me compile! Scroll down for hints :) fn main() { - let x; + let x = 10; if x == 10 { println!("Ten!"); } else { @@ -10,34 +10,6 @@ fn main() { } } - - - - - - - - - - - - - - - - - - - - - - - - - - - - // The compiler message is saying that Rust cannot infer the type that the // variable binding `x` has with what is given here. // What happens if you annotate line 5 with a type annotation? diff --git a/exercises/variables/variables3.rs b/exercises/variables/variables3.rs index 165a277951..d098441fb7 100644 --- a/exercises/variables/variables3.rs +++ b/exercises/variables/variables3.rs @@ -2,42 +2,12 @@ // Make me compile! Scroll down for hints :) fn main() { - let x = 3; + let mut x = 3; println!("Number {}", x); x = 5; println!("Number {}", x); } - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // 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. diff --git a/exercises/variables/variables4.rs b/exercises/variables/variables4.rs index 71ebf0f09b..fed2c475c6 100644 --- a/exercises/variables/variables4.rs +++ b/exercises/variables/variables4.rs @@ -2,42 +2,10 @@ // Make me compile! Scroll down for hints :) fn main() { - let x: i32; + let x: i32 = 1; println!("Number {}", x); } - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Oops! In this exercise, we have a variable binding that we've created on // line 5, and we're trying to use it on line 6, but we haven't given it a // value. We can't print out something that isn't there; try giving x a value!