diff --git a/exercises/closures/README.md b/exercises/closures/README.md index 66a34789..d651ef95 100644 --- a/exercises/closures/README.md +++ b/exercises/closures/README.md @@ -9,8 +9,8 @@ Closures are often used as arguments to higher order functions (functions which take other functions as parameters), e.g. map(), filter(), reduce() et al on iterators, but aren't restricted to these cases. -Rust's ownership model means that we might have to do something extra when declaring -closures which other languages don't require. +Rust's ownership model means that we may need to think about how captured values +are treated: copied, moved, or borrowed immutably or mutably. ## Further information diff --git a/exercises/closures/closures1.rs b/exercises/closures/closures1.rs index 05feb46f..b2858c9e 100644 --- a/exercises/closures/closures1.rs +++ b/exercises/closures/closures1.rs @@ -1,6 +1,6 @@ // closures1.rs // Closures are anonymous functions, but they can be assigned to a variable -// so that they can be used later on +// so that they can be used later on. // make me compile and pass // Execute `rustlings hint closures1` for hints! diff --git a/exercises/closures/closures4.rs b/exercises/closures/closures4.rs index da10c15a..e5f70dd0 100644 --- a/exercises/closures/closures4.rs +++ b/exercises/closures/closures4.rs @@ -1,10 +1,10 @@ // closure4.rs -// Where are you going to use closures? Where the context defines the code +// Where are you going to use closures? Where the context defines the logic // you want some other code to invoke. So, unlike functions or methods, closures // are for when the code is not generally useful, or attached to a // type, but is specific to the context you are defining it in. Closures can -// define parameters, just like functions, but these are defined by the context -// it is intended to run in, where the actual arguments will be supplied. +// define parameters, just like functions, but these are specified by the context +// the closure is intended to be invoked in, where the actual arguments will be supplied. // https://doc.rust-lang.org/stable/std/primitive.slice.html#method.sort_by // Execute `rustlings hint closures4` for hints! diff --git a/exercises/closures/closures5.rs b/exercises/closures/closures5.rs index b0f54f67..d4dddf62 100644 --- a/exercises/closures/closures5.rs +++ b/exercises/closures/closures5.rs @@ -1,9 +1,8 @@ // closure5.rs // These are some fairly common uses of closures on iterator methods // https://doc.rust-lang.org/stable/std/iter/trait.Iterator.html#method.map +// https://doc.rust-lang.org/stable/std/iter/trait.Iterator.html#method.reduce // https://doc.rust-lang.org/stable/std/iter/trait.Iterator.html#method.fold -// my original version used 'reduce()' instead of 'fold()' but why would that -// be unsuitable for a sum function in Rust (specifically)? // Execute `rustlings hint closures5` for hints! @@ -12,16 +11,19 @@ fn count_letters(animals: &Vec<&str>) -> Vec{ // the compiler should help you figure out what signature to use // after you annotate it with one that fails. + // TODO: fill in this line with closure that compiles and passes the test. let count_closure = ; animals.iter().map(count_closure).collect() } fn sum_letters(animals: &Vec<&str>) -> usize { - let sum_closure = let animals = count_letters(animals); - // pay close attention to the where clause in the function signature + // pay close attention to the where clause in the function signatures + // https://doc.rust-lang.org/stable/std/iter/trait.Iterator.html#method.reduce // https://doc.rust-lang.org/stable/std/iter/trait.Iterator.html#method.fold - animals.iter().fold(0, sum_closure) + // TODO: change the next 2 lines to compile and pass the test. + let sum_closure = |x: &usize, y: &usize| &(x + y); + animals.iter().reduce(sum_closure).unwrap().to_owned() } fn main() { @@ -36,7 +38,7 @@ mod tests { use super::*; # [test] - fn test_() { + fn test_closures() { let animals= vec!["cat","fish","horse"]; assert_eq!(vec![3,4,5], count_letters(&animals)); assert_eq!(12, sum_letters(&animals)); diff --git a/exercises/closures/closures6.rs b/exercises/closures/closures6.rs new file mode 100644 index 00000000..b1ea9d84 --- /dev/null +++ b/exercises/closures/closures6.rs @@ -0,0 +1,25 @@ +// closure6.rs +// The compiler will take care of inferring the correct types for +// closures you write: +// https://doc.rust-lang.org/book/ch13-01-closures.html#capturing-the-environment-with-closures +// But if you want to make sure that values are inaccessible after +// the closure, they can be moved rather than borrowed using the 'move' keyword. +// Make me compile! + +// Execute `rustlings hint closures6` for hints! + +// I AM NOT DONE + +fn move_it() { + let who_wants_to = vec!["I want to ", "He wants to ", "They want to "]; + let do_what = String::from("move it"); + + let chorus: Vec = who_wants_to.iter().map( move |&who| who.to_owned() + do_what.as_str() + ", " + do_what.as_str() + ".").collect(); + println!("{:?}",chorus); + + println!("{:?}!",do_what.to_uppercase()); +} + +fn main() { + move_it(); +} \ No newline at end of file diff --git a/exercises/closures/mod.rs b/exercises/closures/mod.rs index e49f3704..1a759063 100644 --- a/exercises/closures/mod.rs +++ b/exercises/closures/mod.rs @@ -3,3 +3,4 @@ mod closures2; mod closures3; mod closures4; mod closures5; +mod closures6; diff --git a/info.toml b/info.toml index 4c8ec94c..40f9ee1a 100644 --- a/info.toml +++ b/info.toml @@ -160,14 +160,15 @@ name = "closures3" path = "exercises/closures/closures3.rs" mode = "compile" hint = """ -The compiler has got you covered with this. After all, why IS it called a closure?""" +The compiler has got you covered with this. After all, why IS it called a closure? +If you actually want to make it work, you can add a parameter to the function.""" [[exercises]] name = "closures4" path = "exercises/closures/closures4.rs" mode = "test" hint = """ -Don't try to actually implement any comparison other than using cmp: +Don't try to actually implement any comparison logic other than invoking cmp: https://doc.rust-lang.org/stable/std/cmp/trait.Ord.html#tymethod.cmp e.g. x.cmp(y)""" @@ -176,9 +177,22 @@ name = "closures5" path = "exercises/closures/closures5.rs" mode = "test" hint = """ -Honestly this was hard to write. Getting the signatures of closures right can be tough. -Pay close attention to the documentation linked to in the exercise and which type -parameters are the same in the function signatures.""" +Getting the signatures of closures right can be tough. I don't think you can write +any version that fulfills the tests using 'reduce()': you can never return a borrow +of a value owned by a called function. +You need to replace 'reduce()' with a different function call, update the closure +so that it matches the signature of this new call, and change the code to return +the correct type from the sum_letters function. (Using 'sum()' is cheating!) +Pay close attention to the documentation linked to in the exercise: which type +parameters are the same in the function signatures, and which are different.""" + +[[exercises]] +name = "closures6" +path = "exercises/closures/closures6.rs" +mode = "compile" +hint = """ +There are two ways to solve this, neither is difficult and both involve just removing +the offending part. If you're thinking hard, you've missed the point.""" # IF