Closure – Why is the value move here to a closed instead of borrow?

The Error Handling chapter of the Rust Book contains examples of how to use the Combiner of Option and Result. Read the file and apply a series of combinators to parse the content into i32 and enter Result

This is a code example:

use std::fs::File;
use std::io::Read;< br />use std::path::Path;

fn file_double>(file_path: P) -> Result {
File: :open(file_path)
.map_err(|err| err.to_string())
.and_then(|mut file| {
let mut contents = String::new(); // local value
file.read_to_string(&mut contents)
.map_err(|err| err.to_string())
.map(|_| contents) // moved without'move'
})
.and_then(|contents| {
contents.trim().parse::()
.map_err(|err| err.to_string())< br /> })
.map(|n| 2 * n)
}

fn main() {
match file_double("foobar") {
Ok(n) => println!("{}", n),
Err(err) => println!("Error: {}" , err),
}
}

The value I am referring to is the content. It is created in the map composer applied to std::io::Result And will be quoted later. The return value of Read :: read_to_string.
Question: I think that without moving the mark closure will borrow any reference value by default, which will cause the borrow checker to complain that the content is not long enough. However, this code It compiles well. This means that the String content is moved into the closure, and then moved out of the closure. Why is it done without a clear move?

I thought that not marking the closure with move would borrow any referenced value by default,

Incomplete. The compiler performs some checks on the code in the closure body and tracks how the closed variable is used.

< p>When the compiler finds that a method is called on a variable, it will look at the type of the receiver (self, & self, & mut self). When the variable is used as a parameter, the compiler will also pass value, reference or variable reference Let’s keep track of it. No matter what the strictest requirement is, what is used by default.

Occasionally, this kind of analysis is not complete enough-even if the variable is only used as a reference, we intend to let the closure own the variable. This It usually happens when the closure is returned or handed over to another thread.

In this case, the variable is returned from the closure, which necessarily means that it is used by value. So the variable will automatically move into the closure Package.

Occasionally the move keyword is too big, because it will move all referenced variables. Sometimes you may just want to force the move in one variable and not the others. In this case, what I know The best solution is to make a clear reference and move the reference:

fn main() {
let a = 1;
let b = 2 ;

{
let b = &b;
needs_to_own_a(move || a_function(a, b));
}
}

The Error Handling chapter of the Rust Book contains examples of how to use the Combiner of Option and Result. Read the file and parse the content into i32 by applying a series of combinators and enter the Result< i32

This is a code example:

use std::fs::File;
use std::io::Read;
use std::path::Path;

fn file_double>(file_path: P) -> Result {
File::open(file_path)
.map_err(|err| err.to_string())
. and_then(|mut file| {
let mut contents = String::new(); // local value
file.read_to_string(&mut contents)
.map_err(|err| err.to_string ())
.map(|_| contents) // moved without'move'
})
.and_then(|contents| {
contents.trim().parse ::()
.map_err(|err| err.to_string())
})
.map(|n| 2 * n)
}

fn main() {
match file_double("foobar") {
Ok(n) => println!("{}", n),
Err( err) => println!("Error: {}", err),
}
}

The value I mean is content. It is applied to std:: Created in the map combiner of io::Result and later referenced. The return value of Read::read_to_string.
Q Question: I think the closure without moving the mark will borrow any reference value by default, which will cause the borrow checker to complain that the content is not long enough. However, this code compiles well. This means that the String content is moved into the closure. And then it was removed from the closure. Why did it complete without a clear move?

I thought that not marking the closure with move would borrow any referenced value by default,

Incomplete. The compiler performs some checks on the code in the closure body and tracks how the closed variable is used.

When the compiler finds that the method is called on the variable , It will look at the receiver’s type (self, & self, & mut self). When a variable is used as a parameter, the compiler will also track it by value, reference or variable reference. No matter what the strictest requirement is, What is used by default.

Occasionally, this analysis is not complete enough-even if the variable is only used as a reference, we intend to let the closure own the variable. This usually happens when returning the closure or handing it over to another One thread.

In this case, the variable is returned from the closure, which necessarily means that it is used by value. Therefore the variable will automatically move into the closure.

Occasionally move the key The word is too big because it moves all referenced variables. Sometimes you may just want to force one variable in and not the others. In this case, the best solution I know is to make an explicit reference and move Quote:

fn main() {
let a = 1;
let b = 2;

{
let b = &b;
needs_to_own_a(move || a_function(a, b));
}
}

Leave a Comment

Your email address will not be published.