@@ -10,39 +10,41 @@ implement special [`Fn`](https://doc.rust-lang.org/std/ops/trait.Fn.html),
10
10
[ ` FnOnce ` ] ( https://doc.rust-lang.org/std/ops/trait.FnOnce.html ) traits:
11
11
12
12
``` rust,editable
13
- fn apply_with_log(func: impl FnOnce(i32) -> i32, input: i32) -> i32 {
14
- println!("Calling function on {input}");
15
- func(input)
13
+ fn apply_and_log(func: impl FnOnce(i32) -> i32, func_name: &str, input: i32) {
14
+ println!("Calling {func_name}({input}): {}", func(input))
16
15
}
17
16
18
17
fn main() {
19
- let add_3 = |x| x + 3;
20
- println!("add_3: {}", apply_with_log(add_3, 10));
21
- println!("add_3: {}", apply_with_log(add_3, 20));
18
+ let n = 3;
19
+ let add_3 = |x| x + n;
20
+ apply_and_log(&add_3, "add_3", 10);
21
+ apply_and_log(&add_3, "add_3", 20);
22
22
23
23
let mut v = Vec::new();
24
24
let mut accumulate = |x: i32| {
25
25
v.push(x);
26
26
v.iter().sum::<i32>()
27
27
};
28
- println!("accumulate: {}", apply_with_log( &mut accumulate, 4) );
29
- println!("accumulate: {}", apply_with_log( &mut accumulate, 5) );
28
+ apply_and_log( &mut accumulate, "accumulate", 4 );
29
+ apply_and_log( &mut accumulate, "accumulate", 5 );
30
30
31
31
let multiply_sum = |x| x * v.into_iter().sum::<i32>();
32
- println!(" multiply_sum: {}", apply_with_log( multiply_sum, 3) );
32
+ apply_and_log( multiply_sum, " multiply_sum" , 3);
33
33
}
34
34
```
35
35
36
36
<details >
37
37
38
- An ` Fn ` (e.g. ` add_3 ` ) neither consumes nor mutates captured values, or perhaps
39
- captures nothing at all. It can be called multiple times concurrently.
38
+ An ` Fn ` (e.g. ` add_3 ` ) neither consumes nor mutates captured values. It can be
39
+ called needing only a shared reference to the closure, which means the closure
40
+ can be executed repeatedly and even concurrently.
40
41
41
- An ` FnMut ` (e.g. ` accumulate ` ) might mutate captured values. You can call it
42
- multiple times, but not concurrently.
42
+ An ` FnMut ` (e.g. ` accumulate ` ) might mutate captured values. The closure object
43
+ is accessed via exclusive reference, so it can be called repeatedly but not
44
+ concurrently.
43
45
44
- If you have an ` FnOnce ` (e.g. ` multiply_sum ` ), you may only call it once. It
45
- might consume captured values.
46
+ If you have an ` FnOnce ` (e.g. ` multiply_sum ` ), you may only call it once. Doing
47
+ so consumes the closure and any values captured by move .
46
48
47
49
` FnMut ` is a subtype of ` FnOnce ` . ` Fn ` is a subtype of ` FnMut ` and ` FnOnce ` .
48
50
I.e. you can use an ` FnMut ` wherever an ` FnOnce ` is called for, and you can use
@@ -52,14 +54,17 @@ When you define a function that takes a closure, you should take `FnOnce` if you
52
54
can (i.e. you call it once), or ` FnMut ` else, and last ` Fn ` . This allows the
53
55
most flexibility for the caller.
54
56
55
- In contrast, when you have a closure, the most flexible you can have is ` Fn ` (it
56
- can be passed everywhere), then ` FnMut ` , and lastly ` FnOnce ` .
57
+ In contrast, when you have a closure, the most flexible you can have is ` Fn `
58
+ (which can be passed to a consumer of any of the 3 closure traits), then
59
+ ` FnMut ` , and lastly ` FnOnce ` .
57
60
58
61
The compiler also infers ` Copy ` (e.g. for ` add_3 ` ) and ` Clone ` (e.g.
59
- ` multiply_sum ` ), depending on what the closure captures.
62
+ ` multiply_sum ` ), depending on what the closure captures. Function pointers
63
+ (references to ` fn ` items) implement ` Copy ` and ` Fn ` .
60
64
61
- By default, closures will capture by reference if they can. The ` move ` keyword
62
- makes them capture by value.
65
+ By default, closures will capture each variable from an outer scope by the least
66
+ demanding form of access they can (by shared reference if possible, then
67
+ exclusive reference, then by move). The ` move ` keyword forces capture by value.
63
68
64
69
``` rust,editable
65
70
fn make_greeter(prefix: String) -> impl Fn(&str) {
0 commit comments