mirror of
https://github.com/google/comprehensive-rust.git
synced 2024-12-14 22:15:54 +02:00
Tweak speaker note about move closures and FnOnce (#859)
* Tweak speaker note about move closures and FnOnce * Expand closure example, explain move * Explicitly state traits of example closures
This commit is contained in:
parent
3150163f95
commit
9fc92c5d66
@ -13,26 +13,51 @@ fn apply_with_log(func: impl FnOnce(i32) -> i32, input: i32) -> i32 {
|
||||
|
||||
fn main() {
|
||||
let add_3 = |x| x + 3;
|
||||
let mul_5 = |x| x * 5;
|
||||
|
||||
println!("add_3: {}", apply_with_log(add_3, 10));
|
||||
println!("mul_5: {}", apply_with_log(mul_5, 20));
|
||||
println!("add_3: {}", apply_with_log(add_3, 20));
|
||||
|
||||
let mut v = Vec::new();
|
||||
let mut accumulate = |x: i32| {
|
||||
v.push(x);
|
||||
v.iter().sum::<i32>()
|
||||
};
|
||||
println!("accumulate: {}", apply_with_log(&mut accumulate, 4));
|
||||
println!("accumulate: {}", apply_with_log(&mut accumulate, 5));
|
||||
|
||||
let multiply_sum = |x| x * v.into_iter().sum::<i32>();
|
||||
println!("multiply_sum: {}", apply_with_log(multiply_sum, 3));
|
||||
}
|
||||
```
|
||||
|
||||
<details>
|
||||
|
||||
If you have an `FnOnce`, you may only call it once. It might consume captured values.
|
||||
An `Fn` (e.g. `add_3`) neither consumes nor mutates captured values, or perhaps captures
|
||||
nothing at all. It can be called multiple times concurrently.
|
||||
|
||||
An `FnMut` might mutate captured values, so you can call it multiple times but not concurrently.
|
||||
An `FnMut` (e.g. `accumulate`) might mutate captured values. You can call it multiple times,
|
||||
but not concurrently.
|
||||
|
||||
An `Fn` neither consumes nor mutates captured values, or perhaps captures nothing at all, so it can
|
||||
be called multiple times concurrently.
|
||||
If you have an `FnOnce` (e.g. `multiply_sum`), you may only call it once. It might consume
|
||||
captured values.
|
||||
|
||||
`FnMut` is a subtype of `FnOnce`. `Fn` is a subtype of `FnMut` and `FnOnce`. I.e. you can use an
|
||||
`FnMut` wherever an `FnOnce` is called for, and you can use an `Fn` wherever an `FnMut` or `FnOnce`
|
||||
is called for.
|
||||
|
||||
`move` closures only implement `FnOnce`.
|
||||
The compiler also infers `Copy` (e.g. for `add_3`) and `Clone` (e.g. `multiply_sum`),
|
||||
depending on what the closure captures.
|
||||
|
||||
By default, closures will capture by reference if they can. The `move` keyword makes them capture
|
||||
by value.
|
||||
```rust,editable
|
||||
fn make_greeter(prefix: String) -> impl Fn(&str) {
|
||||
return move |name| println!("{} {}", prefix, name)
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let hi = make_greeter("Hi".to_string());
|
||||
hi("there");
|
||||
}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
Loading…
Reference in New Issue
Block a user