Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chapter 13 about FnOnce clousure definition #4011

Closed
llianc62 opened this issue Aug 15, 2024 · 2 comments
Closed

chapter 13 about FnOnce clousure definition #4011

llianc62 opened this issue Aug 15, 2024 · 2 comments

Comments

@llianc62
Copy link

llianc62 commented Aug 15, 2024

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

  1. FnOnce applies 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 implement FnOnce and none of the other Fn traits, because it can only be called once.
  2. FnMut applies 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.
  3. Fn applies 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?

@llianc62 llianc62 changed the title chapter 13 about FnOnceclousure definition chapter 13 about FnOnce clousure definition Aug 15, 2024
@llianc62
Copy link
Author

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

@chriskrycho
Copy link
Contributor

chriskrycho commented Sep 30, 2024

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!

@chriskrycho chriskrycho closed this as not planned Won't fix, can't repro, duplicate, stale Sep 30, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants