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-30 21:47:47 +01:00
parent 5a52092109
commit f9a4ff3b82
10 changed files with 215 additions and 4 deletions

View File

@ -0,0 +1,17 @@
# Closures
Closures are a common programming concept found in many languages, but are primarily
associated with 'functional' programming styles. Closure are anonymous functions
(i.e. unlike regular functions, they don't have a name) that may access some variables
from their enclosing scope (they 'close' over their scope, capturing variables).
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.
## Further information
- [Closures: Anonymous Functions that Can Capture Their Environment](https://doc.rust-lang.org/book/ch13-01-closures.html)

View File

@ -0,0 +1,21 @@
// closures1.rs
// Closures are anonymous functions, but they can be assigned to a variable
// so that they can be used later on
// make me compile and pass
// Execute `rustlings hint closures1` for hints!
// I AM NOT DONE
fn main() {}
#[cfg(test)]
mod tests {
use super::*;
# [test]
fn test_closure() {
let closure = ;
assert_eq!("I'm a closure",closure());
}
}

View File

@ -0,0 +1,24 @@
// closure2.rs
// What is the difference between a closure and a function? Can you get this code
// to compile?
// Execute `rustlings hint closures2` for hints!
// I AM NOT DONE
fn output(closure) {
println!("What am I?");
closure();
}
fn main() {
fn actual() {
println!("I'm actually a function")
}
let actual_fn = actual;
let closure = || println!("I'm a closure");
output(closure);
output(actual_fn);
}

View File

@ -0,0 +1,24 @@
// closure3.rs
// What is the difference between a closure and a function, part II? Can you get this code
// to compile?
// Execute `rustlings hint closures3` for hints!
// I AM NOT DONE
fn main() {
let my_name = String::from("Lim Lady");
fn actual() {
println!("my name is: {}", my_name);
}
let actual_fn = actual;
let closure = || {
println!("my name is: {}", my_name);
};
println!("Who am I?");
actual_fn();
closure();
}

View File

@ -0,0 +1,34 @@
// closure4.rs
// Where are you going to use closures? Where the context defines the code
// 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.
// https://doc.rust-lang.org/stable/std/primitive.slice.html#method.sort_by
// Execute `rustlings hint closures4` for hints!
// I AM NOT DONE
fn alphabetize(list: &mut Vec<&str>) {
list.sort_by();
}
fn main() {
let mut list = vec!("Oliver","Tarquinn","Bertrude");
println!("before {:?}",list);
alphabetize(& mut list);
println!("after {:?}",list);
}
#[cfg(test)]
mod tests {
use super::*;
# [test]
fn test_alphabetize() {
let mut list = vec!("Oliver","Tarquinn","Bertrude");
assert_eq!(vec!("Bertrude","Oliver","Tarquinn"),alphabetize(&mut list));
}
}

View File

@ -0,0 +1,44 @@
// 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.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!
// I AM NOT DONE
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.
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
// https://doc.rust-lang.org/stable/std/iter/trait.Iterator.html#method.fold
animals.iter().fold(0, sum_closure)
}
fn main() {
let animals= vec!["cat","fish","horse"];
println!("animals: {:?}",animals);
println!("length: {:?}", count_letters(&animals));
println!("total: {:?}", sum_letters(&animals));
}
#[cfg(test)]
mod tests {
use super::*;
# [test]
fn test_() {
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,5 @@
mod closures1;
mod closures2;
mod closures3;
mod closures4;
mod closures5;

View File

@ -1,4 +1 @@
mod hashmap1; mod closures1;
mod hashmap2;
mod vec1;
mod vec2;

View File

@ -25,3 +25,4 @@ mod threads;
mod traits; mod traits;
mod variables; mod variables;
mod lifetimes; mod lifetimes;
mod closures;

View File

@ -136,6 +136,50 @@ They are not the same. There are two solutions:
1. Add a `return` ahead of `num * num;` 1. Add a `return` ahead of `num * num;`
2. remove `;`, make it to be `num * num`""" 2. remove `;`, make it to be `num * num`"""
# CLOSURES
[[exercises]]
name = "closures1"
path = "exercises/closures/closures1.rs"
mode = "test"
hint = """
Take a look at this section of the book: https://doc.rust-lang.org/book/ch13-01-closures.html"""
[[exercises]]
name = "closures2"
path = "exercises/closures/closures2.rs"
mode = "compile"
hint = """
A bit taxing, but these should help:
https://doc.rust-lang.org/rust-by-example/fn/closures/input_parameters.html
https://doc.rust-lang.org/rust-by-example/fn/closures/anonymity.html
https://doc.rust-lang.org/rust-by-example/fn/closures/input_functions.html"""
[[exercises]]
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?"""
[[exercises]]
name = "closures4"
path = "exercises/closures/closures4.rs"
mode = "test"
hint = """
Don't try to actually implement any comparison other than using cmp:
https://doc.rust-lang.org/stable/std/cmp/trait.Ord.html#tymethod.cmp
e.g. x.cmp(y)"""
[[exercises]]
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."""
# IF # IF
[[exercises]] [[exercises]]