book
book copied to clipboard
chapter 13 about FnOnce clousure definition
URL to the section(s) of the book with this problem: https://doc.rust-lang.org/book/ch13-01-closures.html#moving-captured-values-out-of-closures-and-the-fn-traits
FnOnceapplies to closures that can be called once. All closures implement at least this trait, because all closures can be called. A closure that moves captured values out of its body will only implementFnOnceand none of the otherFntraits, because it can only be called once.FnMutapplies to closures that don’t move captured values out of their body, but that might mutate the captured values. These closures can be called more than once.Fnapplies to closures that don’t move captured values out of their body and that don’t mutate captured values, as well as closures that capture nothing from their environment. These closures can be called more than once without mutating their environment, which is important in cases such as calling a closure multiple times concurrently.
A closure that moves captured values out of its body will only implement
FnOnce
I thought it could be: A closure that moves captured values in of its body will only implement FnOnce ?
in or out?
Like this :
let x = String::from("hello");
let consume_x = move || {
println!("{}", x);
};
consume_x(); // closure take the ownership
// consume_x(); // can not execute because `x` is moved
This is a tricky one, but the terminology here is correct. If you try running the code you showed, it works just fine! Here’s a playground which demonstrates that. (Also notice that println! borrows its argument here!) Your code does move ownership into the closure, but it does not moves it out. That means your example implements Fn as well as FnOnce.
If you returned the value from the closure at the end, like this, however, it would only implement FnOnce, because the value would have been moved out of the closure, just as the text says:
let x = String::from("hello");
let consume_x = move || {
println!("{}", x);
x
};
consume_x(); // closure take the ownership
consume_x(); // can not execute because `x` is moved
This has the error you expected from the println example (playground)
There are two main ways to move a value out of a closure: returning it, or passing it to a function which takes ownership of it.
Hope that helps!