mirror of
https://github.com/rust-lang/rustlings.git
synced 2026-01-11 13:19:18 +00:00
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:
parent
5a52092109
commit
f9a4ff3b82
17
exercises/closures/README.md
Normal file
17
exercises/closures/README.md
Normal 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)
|
||||
21
exercises/closures/closures1.rs
Normal file
21
exercises/closures/closures1.rs
Normal 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());
|
||||
}
|
||||
}
|
||||
24
exercises/closures/closures2.rs
Normal file
24
exercises/closures/closures2.rs
Normal 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);
|
||||
}
|
||||
24
exercises/closures/closures3.rs
Normal file
24
exercises/closures/closures3.rs
Normal 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();
|
||||
}
|
||||
34
exercises/closures/closures4.rs
Normal file
34
exercises/closures/closures4.rs
Normal 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));
|
||||
}
|
||||
}
|
||||
44
exercises/closures/closures5.rs
Normal file
44
exercises/closures/closures5.rs
Normal 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));
|
||||
}
|
||||
}
|
||||
5
exercises/closures/mod.rs
Normal file
5
exercises/closures/mod.rs
Normal file
@ -0,0 +1,5 @@
|
||||
mod closures1;
|
||||
mod closures2;
|
||||
mod closures3;
|
||||
mod closures4;
|
||||
mod closures5;
|
||||
@ -1,4 +1 @@
|
||||
mod hashmap1;
|
||||
mod hashmap2;
|
||||
mod vec1;
|
||||
mod vec2;
|
||||
mod closures1;
|
||||
|
||||
@ -25,3 +25,4 @@ mod threads;
|
||||
mod traits;
|
||||
mod variables;
|
||||
mod lifetimes;
|
||||
mod closures;
|
||||
|
||||
44
info.toml
44
info.toml
@ -136,6 +136,50 @@ They are not the same. There are two solutions:
|
||||
1. Add a `return` ahead of `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
|
||||
|
||||
[[exercises]]
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user