Skip to content

Commit f85fb0d

Browse files
committed
Add closures2.rs
1 parent c26e739 commit f85fb0d

4 files changed

Lines changed: 110 additions & 0 deletions

File tree

dev/Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,10 @@ bin = [
140140
{ name = "tests2_sol", path = "../solutions/17_tests/tests2.rs" },
141141
{ name = "tests3", path = "../exercises/17_tests/tests3.rs" },
142142
{ name = "tests3_sol", path = "../solutions/17_tests/tests3.rs" },
143+
{ name = "closures1", path = "../exercises/18_closures/closures1.rs" },
144+
{ name = "closures1_sol", path = "../solutions/18_closures/closures1.rs" },
145+
{ name = "closures2", path = "../exercises/18_closures/closures2.rs" },
146+
{ name = "closures2_sol", path = "../solutions/18_closures/closures2.rs" },
143147
{ name = "iterators1", path = "../exercises/18_iterators/iterators1.rs" },
144148
{ name = "iterators1_sol", path = "../solutions/18_iterators/iterators1.rs" },
145149
{ name = "iterators2", path = "../exercises/18_iterators/iterators2.rs" },

exercises/18_closures/closures2.rs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// closures2.rs
2+
//
3+
// How do closures capture their state? Well, the answer is "it depends on how you use it!"
4+
//
5+
// Usage inside the closure body will tell the compiler how the value should be captured.
6+
//
7+
// Capture by shared reference? Mutable reference? Ownership? Let's try and see!
8+
//
9+
// Execute `rustlings hint closures2` or use the `hint` watch subcommand for a hint.
10+
11+
fn main() {
12+
// Using a non-Copy type because it makes reasoning about capturing easier
13+
let s = String::from("Hello, rustlings!");
14+
let capture_by_ref = || {
15+
println!("{s}"); // This only requires a &String, so it only captures a &String
16+
};
17+
// You can continue to use s as a &String outside the closure, but not &mut String or String.
18+
println!("Outside capture_by_ref closure: {s}");
19+
capture_by_ref();
20+
21+
// Notice the mut here
22+
// v
23+
let mut s = String::from("Hello, rustlings!");
24+
let mut capture_by_mut = || {
25+
s.truncate(5); // Requires &mut String: also can be written as String::truncate(&mut s, 5);
26+
println!("{s}"); // This should print nothing (and a line break)
27+
// Since the "most" we need is mutable, it captures a single mutable reference to String.
28+
};
29+
capture_by_mut();
30+
31+
let mut s = String::from("Hello, rustlings!");
32+
let capture_by_ownership = || {
33+
s.truncate(5); // Requires &mut String
34+
println!("{s}"); // This should print nothing (and a line break)
35+
let boxed = s.into_boxed_str(); // Requires ownership: String::into_boxed_str(s);
36+
println!("{boxed}"); // This should print nothing (and a line break)
37+
};
38+
capture_by_ownership();
39+
40+
let mut s = String::from("Hello, rustlings!");
41+
let mut quiz = || {
42+
let captured_s = &mut s; // TODO Fix this compiler error
43+
println!("Inside Closure quiz {captured_s}");
44+
};
45+
println!("Outside Closure quiz {s}");
46+
quiz();
47+
}

rustlings-macros/info.toml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -878,11 +878,23 @@ https://doc.rust-lang.org/book/ch11-01-writing-tests.html#checking-for-panics-wi
878878
[[exercises]]
879879
name = "closures1"
880880
dir = "18_closures"
881+
test = false
881882
hint = """
882883
Self is a concept that is only used in struct/enum methods.
883884
884885
Closures in Rust do not have a self to refer to, unlike other languages that might use this or self."""
885886

887+
[[exercises]]
888+
name = "closures2"
889+
dir = "18_closures"
890+
test = false
891+
hint = """
892+
Capturing a mutable reference manually will also force the closure to capture s by mutable reference.
893+
894+
The println macro only requires a shared reference.
895+
896+
Also make sure that you don't declare s or the closure with mut when it is no longer necessary."""
897+
886898
# STANDARD LIBRARY TYPES
887899

888900
[[exercises]]

solutions/18_closures/closures2.rs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// closures2.rs
2+
//
3+
// How do closures capture their state? Well, the answer is "it depends on how you use it!"
4+
//
5+
// Usage inside the closure body will tell the compiler how the value should be captured.
6+
//
7+
// Capture by shared reference? Mutable reference? Ownership? Let's try and see!
8+
//
9+
// Execute `rustlings hint closures2` or use the `hint` watch subcommand for a hint.
10+
11+
fn main() {
12+
// Using a non-Copy type because it makes reasoning about capturing easier
13+
let s = String::from("Hello, rustlings!");
14+
let capture_by_ref = || {
15+
println!("{s}"); // This only requires a &String, so it only captures a &String
16+
};
17+
// You can continue to use s as a &String outside the closure, but not &mut String or String.
18+
println!("Outside capture_by_ref closure: {s}");
19+
capture_by_ref();
20+
21+
// Notice the mut here
22+
// v
23+
let mut s = String::from("Hello, rustlings!");
24+
let mut capture_by_mut = || {
25+
s.truncate(5); // Requires &mut String: also can be written as String::truncate(&mut s, 5);
26+
println!("{s}"); // This should print nothing (and a line break)
27+
// Since the "most" we need is mutable, it captures a single mutable reference to String.
28+
};
29+
capture_by_mut();
30+
31+
let mut s = String::from("Hello, rustlings!");
32+
let capture_by_ownership = || {
33+
s.truncate(5); // Requires &mut String
34+
println!("{s}"); // This should print nothing (and a line break)
35+
let boxed = s.into_boxed_str(); // Requires ownership: String::into_boxed_str(s);
36+
println!("{boxed}"); // This should print nothing (and a line break)
37+
};
38+
capture_by_ownership();
39+
40+
let s = String::from("Hello, rustlings!");
41+
let quiz = || {
42+
let captured_s = &s; // Using a shared reference fixes the issue.
43+
println!("Inside Closure quiz {captured_s}");
44+
};
45+
println!("Outside Closure quiz {s}");
46+
quiz();
47+
}

0 commit comments

Comments
 (0)