mirror of
https://github.com/rust-lang/rustlings.git
synced 2024-12-25 23:10:30 +00:00
Add closures2.rs
This commit is contained in:
parent
d9cfdf7c65
commit
8aa8b492ea
4 changed files with 110 additions and 0 deletions
|
@ -140,6 +140,10 @@ bin = [
|
||||||
{ name = "tests2_sol", path = "../solutions/17_tests/tests2.rs" },
|
{ name = "tests2_sol", path = "../solutions/17_tests/tests2.rs" },
|
||||||
{ name = "tests3", path = "../exercises/17_tests/tests3.rs" },
|
{ name = "tests3", path = "../exercises/17_tests/tests3.rs" },
|
||||||
{ name = "tests3_sol", path = "../solutions/17_tests/tests3.rs" },
|
{ name = "tests3_sol", path = "../solutions/17_tests/tests3.rs" },
|
||||||
|
{ name = "closures1", path = "../exercises/18_closures/closures1.rs" },
|
||||||
|
{ name = "closures1_sol", path = "../solutions/18_closures/closures1.rs" },
|
||||||
|
{ name = "closures2", path = "../exercises/18_closures/closures2.rs" },
|
||||||
|
{ name = "closures2_sol", path = "../solutions/18_closures/closures2.rs" },
|
||||||
{ name = "iterators1", path = "../exercises/18_iterators/iterators1.rs" },
|
{ name = "iterators1", path = "../exercises/18_iterators/iterators1.rs" },
|
||||||
{ name = "iterators1_sol", path = "../solutions/18_iterators/iterators1.rs" },
|
{ name = "iterators1_sol", path = "../solutions/18_iterators/iterators1.rs" },
|
||||||
{ name = "iterators2", path = "../exercises/18_iterators/iterators2.rs" },
|
{ name = "iterators2", path = "../exercises/18_iterators/iterators2.rs" },
|
||||||
|
|
47
exercises/18_closures/closures2.rs
Normal file
47
exercises/18_closures/closures2.rs
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
// closures2.rs
|
||||||
|
//
|
||||||
|
// How do closures capture their state? Well, the answer is "it depends on how you use it!"
|
||||||
|
//
|
||||||
|
// Usage inside the closure body will tell the compiler how the value should be captured.
|
||||||
|
//
|
||||||
|
// Capture by shared reference? Mutable reference? Ownership? Let's try and see!
|
||||||
|
//
|
||||||
|
// Execute `rustlings hint closures2` or use the `hint` watch subcommand for a hint.
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
// Using a non-Copy type because it makes reasoning about capturing easier
|
||||||
|
let s = String::from("Hello, rustlings!");
|
||||||
|
let capture_by_ref = || {
|
||||||
|
println!("{s}"); // This only requires a &String, so it only captures a &String
|
||||||
|
};
|
||||||
|
// You can continue to use s as a &String outside the closure, but not &mut String or String.
|
||||||
|
println!("Outside capture_by_ref closure: {s}");
|
||||||
|
capture_by_ref();
|
||||||
|
|
||||||
|
// Notice the mut here
|
||||||
|
// v
|
||||||
|
let mut s = String::from("Hello, rustlings!");
|
||||||
|
let mut capture_by_mut = || {
|
||||||
|
s.truncate(5); // Requires &mut String: also can be written as String::truncate(&mut s, 5);
|
||||||
|
println!("{s}"); // This should print nothing (and a line break)
|
||||||
|
// Since the "most" we need is mutable, it captures a single mutable reference to String.
|
||||||
|
};
|
||||||
|
capture_by_mut();
|
||||||
|
|
||||||
|
let mut s = String::from("Hello, rustlings!");
|
||||||
|
let capture_by_ownership = || {
|
||||||
|
s.truncate(5); // Requires &mut String
|
||||||
|
println!("{s}"); // This should print nothing (and a line break)
|
||||||
|
let boxed = s.into_boxed_str(); // Requires ownership: String::into_boxed_str(s);
|
||||||
|
println!("{boxed}"); // This should print nothing (and a line break)
|
||||||
|
};
|
||||||
|
capture_by_ownership();
|
||||||
|
|
||||||
|
let mut s = String::from("Hello, rustlings!");
|
||||||
|
let mut quiz = || {
|
||||||
|
let captured_s = &mut s; // TODO Fix this compiler error
|
||||||
|
println!("Inside Closure quiz {captured_s}");
|
||||||
|
};
|
||||||
|
println!("Outside Closure quiz {s}");
|
||||||
|
quiz();
|
||||||
|
}
|
|
@ -882,11 +882,23 @@ https://doc.rust-lang.org/book/ch11-01-writing-tests.html#checking-for-panics-wi
|
||||||
[[exercises]]
|
[[exercises]]
|
||||||
name = "closures1"
|
name = "closures1"
|
||||||
dir = "18_closures"
|
dir = "18_closures"
|
||||||
|
test = false
|
||||||
hint = """
|
hint = """
|
||||||
Self is a concept that is only used in struct/enum methods.
|
Self is a concept that is only used in struct/enum methods.
|
||||||
|
|
||||||
Closures in Rust do not have a self to refer to, unlike other languages that might use this or self."""
|
Closures in Rust do not have a self to refer to, unlike other languages that might use this or self."""
|
||||||
|
|
||||||
|
[[exercises]]
|
||||||
|
name = "closures2"
|
||||||
|
dir = "18_closures"
|
||||||
|
test = false
|
||||||
|
hint = """
|
||||||
|
Capturing a mutable reference manually will also force the closure to capture s by mutable reference.
|
||||||
|
|
||||||
|
The println macro only requires a shared reference.
|
||||||
|
|
||||||
|
Also make sure that you don't declare s or the closure with mut when it is no longer necessary."""
|
||||||
|
|
||||||
# STANDARD LIBRARY TYPES
|
# STANDARD LIBRARY TYPES
|
||||||
|
|
||||||
[[exercises]]
|
[[exercises]]
|
||||||
|
|
47
solutions/18_closures/closures2.rs
Normal file
47
solutions/18_closures/closures2.rs
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
// closures2.rs
|
||||||
|
//
|
||||||
|
// How do closures capture their state? Well, the answer is "it depends on how you use it!"
|
||||||
|
//
|
||||||
|
// Usage inside the closure body will tell the compiler how the value should be captured.
|
||||||
|
//
|
||||||
|
// Capture by shared reference? Mutable reference? Ownership? Let's try and see!
|
||||||
|
//
|
||||||
|
// Execute `rustlings hint closures2` or use the `hint` watch subcommand for a hint.
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
// Using a non-Copy type because it makes reasoning about capturing easier
|
||||||
|
let s = String::from("Hello, rustlings!");
|
||||||
|
let capture_by_ref = || {
|
||||||
|
println!("{s}"); // This only requires a &String, so it only captures a &String
|
||||||
|
};
|
||||||
|
// You can continue to use s as a &String outside the closure, but not &mut String or String.
|
||||||
|
println!("Outside capture_by_ref closure: {s}");
|
||||||
|
capture_by_ref();
|
||||||
|
|
||||||
|
// Notice the mut here
|
||||||
|
// v
|
||||||
|
let mut s = String::from("Hello, rustlings!");
|
||||||
|
let mut capture_by_mut = || {
|
||||||
|
s.truncate(5); // Requires &mut String: also can be written as String::truncate(&mut s, 5);
|
||||||
|
println!("{s}"); // This should print nothing (and a line break)
|
||||||
|
// Since the "most" we need is mutable, it captures a single mutable reference to String.
|
||||||
|
};
|
||||||
|
capture_by_mut();
|
||||||
|
|
||||||
|
let mut s = String::from("Hello, rustlings!");
|
||||||
|
let capture_by_ownership = || {
|
||||||
|
s.truncate(5); // Requires &mut String
|
||||||
|
println!("{s}"); // This should print nothing (and a line break)
|
||||||
|
let boxed = s.into_boxed_str(); // Requires ownership: String::into_boxed_str(s);
|
||||||
|
println!("{boxed}"); // This should print nothing (and a line break)
|
||||||
|
};
|
||||||
|
capture_by_ownership();
|
||||||
|
|
||||||
|
let s = String::from("Hello, rustlings!");
|
||||||
|
let quiz = || {
|
||||||
|
let captured_s = &s; // Using a shared reference fixes the issue.
|
||||||
|
println!("Inside Closure quiz {captured_s}");
|
||||||
|
};
|
||||||
|
println!("Outside Closure quiz {s}");
|
||||||
|
quiz();
|
||||||
|
}
|
Loading…
Reference in a new issue