feat: added closures exercises in closure directory

Closures as a separate exercises appeared to be missing, so I added some. Have placed them in the watch order after functions, which seemed reasonable.
This commit is contained in:
jayber 2022-05-31 14:00:50 +01:00
parent 600a498187
commit d36d7b32e5
7 changed files with 59 additions and 17 deletions

View File

@ -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

View File

@ -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!

View File

@ -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!

View File

@ -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<usize>{
// 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));

View File

@ -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<String> = 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();
}

View File

@ -3,3 +3,4 @@ mod closures2;
mod closures3;
mod closures4;
mod closures5;
mod closures6;

View File

@ -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