Por que o valor foi transferido para o fechamento aqui em vez de emprestado?
oCapítulo Tratamento de erros do livro Rust contém um exemplo de como usar os combinadores deOption
eResult
. Um arquivo é lido e, através da aplicação de uma série de combinadores, o conteúdo é analisado como umi32
e retornou em umResult<i32, String>
. Agora, fiquei confuso quando olhei o código. Lá, em um fechamento para um e - em seguida, um localString
é criado um valor passado posteriormente como um valor de retorno para outro combinador.
Aqui está o exemplo de código:
use std::fs::File;
use std::io::Read;
use std::path::Path;
fn file_double<P: AsRef<Path>>(file_path: P) -> Result<i32, String> {
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::<i32>()
.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),
}
}
O valor a que me refiro écontents
. Ele é criado e posteriormente referenciado nomap
combinador aplicado aostd::io::Result<usize>
valor de retorno deRead::read_to_string
. A pergunta: eu pensei quenão marcando o fechamento commove
emprestaria qualquer valor referenciado por padrão, o que resultaria na reclamação do verificador de empréstimo, quecontents
não vive o suficiente. No entanto, esse código compila perfeitamente. Isso significa que oString
contents
é movido para dentro e subseqüentemente fora do fechamento. Por que isso é feito sem o explícitomove
?