diff --git a/README.md b/README.md index 82584f0..183a4ed 100644 --- a/README.md +++ b/README.md @@ -96,8 +96,8 @@ Note that the exercises in this section may look similar to each other but they The [Error Handling](https://doc.rust-lang.org/stable/book/error-handling.html) and [Generics](https://doc.rust-lang.org/stable/book/generics.html) sections are relevant. - ["option1.rs"](http://play.rust-lang.org/?code=%2F%2F+This+example+panics+because+the+second+time+it+calls+%60pop%60%2C+the+%60vec%60%0A%2F%2F+is+empty%2C+so+%60pop%60+returns+%60None%60%2C+and+%60unwrap%60+panics+if+it%27s+called%0A%2F%2F+on+%60None%60.+Handle+this+in+a+more+graceful+way+than+calling+%60unwrap%60%21%0A%2F%2F+Scroll+down+for+hints+%3A%29%0A%0Afn+main%28%29+%7B%0A++++let+mut+list+%3D+vec%21%5B3%5D%3B%0A%0A++++let+last+%3D+list.pop%28%29.unwrap%28%29%3B%0A++++println%21%28%22The+last+item+in+the+list+is+%7B%3A%3F%7D%22%2C+last%29%3B%0A%0A++++let+second_to_last+%3D+list.pop%28%29.unwrap%28%29%3B%0A++++println%21%28%22The+second-to-last+item+in+the+list+is+%7B%3A%3F%7D%22%2C+second_to_last%29%3B%0A%7D%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%2F%2F+Try+using+a+%60match%60+statement+where+the+arms+are+%60Some%28thing%29%60+and+%60None%60.%0A%2F%2F+Or+set+a+default+value+to+print+out+if+you+get+%60None%60+by+using+the%0A%2F%2F+function+%60unwrap_or%60.%0A%2F%2F+Or+use+an+%60if+let%60+statement+on+the+result+of+%60pop%28%29%60+to+both+destructure%0A%2F%2F+a+%60Some%60+value+and+only+print+out+something+if+we+have+a+value%21%0A) - - ["result1.rs"](http://play.rust-lang.org/?code=%2F%2F+Make+this+test+pass%21+Scroll+down+for+hints+%3A%29%0A%0A%23%5Bderive%28PartialEq%2CDebug%29%5D%0Astruct+PositiveNonzeroInteger%28u64%29%3B%0A%0A%23%5Bderive%28PartialEq%2CDebug%29%5D%0Aenum+CreationError+%7B%0A++++Negative%2C%0A++++Zero%2C%0A%7D%0A%0Aimpl+PositiveNonzeroInteger+%7B%0A++++fn+new%28value%3A+i64%29+-%3E+Result%3CPositiveNonzeroInteger%2C+CreationError%3E+%7B%0A++++++++Ok%28PositiveNonzeroInteger%28value+as+u64%29%29%0A++++%7D%0A%7D%0A%0A%23%5Btest%5D%0Afn+test_creation%28%29+%7B%0A++++assert%21%28PositiveNonzeroInteger%3A%3Anew%2810%29.is_ok%28%29%29%3B%0A++++assert_eq%21%28Err%28CreationError%3A%3ANegative%29%2C+PositiveNonzeroInteger%3A%3Anew%28-10%29%29%3B%0A++++assert_eq%21%28Err%28CreationError%3A%3AZero%29%2C+PositiveNonzeroInteger%3A%3Anew%280%29%29%3B%0A%7D%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%2F%2F+%60PositiveNonzeroInteger%3A%3Anew%60+is+always+creating+a+new+instance+and+returning+an+%60Ok%60+result.%0A%2F%2F+It+should+be+doing+some+checking%2C+returning+an+%60Err%60+result+if+those+checks+fail%2C+and+only%0A%2F%2F+returning+an+%60Ok%60+result+if+those+checks+determine+that+everything+is...+okay+%3A%29%0A) +- ["errors1.rs"](http://play.rust-lang.org/?code=%2F%2F+This+function+refuses+to+generate+text+to+be+printed+on+a+nametag+if%0A%2F%2F+you+pass+it+an+empty+string.+It%27d+be+nicer+if+it+explained+what+the+problem%0A%2F%2F+was%2C+instead+of+just+sometimes+returning+%60None%60.+The+2nd+test+currently%0A%2F%2F+does+not+compile+or+pass%2C+but+it+illustrates+the+behavior+we+would+like%0A%2F%2F+this+function+to+have.%0A%2F%2F+Scroll+down+for+hints%21%21%21%0A%0Apub+fn+generate_nametag_text%28name%3A+String%29+-%3E+Option%3CString%3E+%7B%0A++++if+name.len%28%29+%3E+0+%7B%0A++++++++Some%28format%21%28%22Hi%21+My+name+is+%7B%7D%22%2C+name%29%29%0A++++%7D+else+%7B%0A++++++++%2F%2F+Empty+names+aren%27t+allowed.%0A++++++++None%0A++++%7D%0A%7D%0A%0A%23%5Bcfg%28test%29%5D%0Amod+tests+%7B%0A++++use+super%3A%3A*%3B%0A%0A++++%2F%2F+This+test+passes+initially+if+you+comment+out+the+2nd+test.%0A++++%2F%2F+You%27ll+need+to+update+what+this+test+expects+when+you+change%0A++++%2F%2F+the+function+under+test%21%0A++++%23%5Btest%5D%0A++++fn+generates_nametag_text_for_a_nonempty_name%28%29+%7B%0A++++++++assert_eq%21%28%0A++++++++++++generate_nametag_text%28%22Beyonc%C3%A9%22.into%28%29%29%2C%0A++++++++++++Some%28%22Hi%21+My+name+is+Beyonc%C3%A9%22.into%28%29%29%0A++++++++%29%3B%0A++++%7D%0A%0A++++%23%5Btest%5D%0A++++fn+explains_why_generating_nametag_text_fails%28%29+%7B%0A++++++++assert_eq%21%28%0A++++++++++++generate_nametag_text%28%22%22.into%28%29%29%2C%0A++++++++++++Err%28%22%60name%60+was+empty%3B+it+must+be+nonempty.%22.into%28%29%29%0A++++++++%29%3B%0A++++%7D%0A%7D%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%2F%2F+%60Err%60+is+one+of+the+variants+of+%60Result%60%2C+so+what+the+2nd+test+is+saying%0A%2F%2F+is+that+%60generate_nametag_text%60+should+return+a+%60Result%60+instead+of+an%0A%2F%2F+%60Option%60.%0A%0A%2F%2F+To+make+this+change%2C+you%27ll+need+to%3A%0A%2F%2F+-+update+the+return+type+in+the+function+signature+to+be+a+Result+that%0A%2F%2F+++could+be+the+variants+%60Ok%28String%29%60+and+%60Err%28String%29%60%0A%2F%2F+-+change+the+body+of+the+function+to+return+%60Ok%28stuff%29%60+where+it+currently%0A%2F%2F+++returns+%60Some%28stuff%29%60%0A%2F%2F+-+change+the+body+of+the+function+to+return+%60Err%28error+message%29%60+where+it%0A%2F%2F+++currently+returns+%60None%60%0A%2F%2F+-+change+the+first+test+to+expect+%60Ok%28stuff%29%60+where+it+currently+expects%0A%2F%2F+++%60Some%28stuff%29%60.%0A) ### Standard library types diff --git a/error_handling/errors1.rs b/error_handling/errors1.rs new file mode 100644 index 0000000..843e620 --- /dev/null +++ b/error_handling/errors1.rs @@ -0,0 +1,72 @@ +// This function refuses to generate text to be printed on a nametag if +// you pass it an empty string. It'd be nicer if it explained what the problem +// was, instead of just sometimes returning `None`. The 2nd test currently +// does not compile or pass, but it illustrates the behavior we would like +// this function to have. +// Scroll down for hints!!! + +pub fn generate_nametag_text(name: String) -> Option { + if name.len() > 0 { + Some(format!("Hi! My name is {}", name)) + } else { + // Empty names aren't allowed. + None + } +} + +#[cfg(test)] +mod tests { + use super::*; + + // This test passes initially if you comment out the 2nd test. + // You'll need to update what this test expects when you change + // the function under test! + #[test] + fn generates_nametag_text_for_a_nonempty_name() { + assert_eq!( + generate_nametag_text("Beyoncé".into()), + Some("Hi! My name is Beyoncé".into()) + ); + } + + #[test] + fn explains_why_generating_nametag_text_fails() { + assert_eq!( + generate_nametag_text("".into()), + Err("`name` was empty; it must be nonempty.".into()) + ); + } +} + + + + + + + + + + + + + + + + + + + + +// `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`. + +// To make this change, you'll need to: +// - update the return type in the function signature to be a Result that +// could be the variants `Ok(String)` and `Err(String)` +// - change the body of the function to return `Ok(stuff)` where it currently +// returns `Some(stuff)` +// - change the body of the function to return `Err(error message)` where it +// currently returns `None` +// - change the first test to expect `Ok(stuff)` where it currently expects +// `Some(stuff)`.