錆書のError Handling chapterには、Option
とResult
という組み合わせを使用する方法の例が含まれています。ファイルが読み込まれ、一連のコンビネータを適用すると、コンテンツはi32
として解析され、Result<i32, String>
に返されます。 コードを見ると混乱します。ここで、and_thenへの1つのクロージャでは、ローカルのString
値が作成され、その後、別のコンビネータに戻り値として渡されます。ここでなぜ借りたのではなく、クロージャーに値を移動したのですか?
はコードの例です:私が参照しています
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),
}
}
値はcontents
です。これは、std::io::Result<usize>
戻り値Read::read_to_string
に適用されたmap
コンビネータで作成され、後で参照されます。 質問:私はではなくと閉鎖をマークするとデフォルトで参照された値が借用され、貸し出しチェッカーが文句を言うことになります。contents
は十分に長くは生きていません。しかし、このコードはうまくコンパイルされます。つまり、String
contents
はクロージャの中に移動され、クロージャの下位に移動されます。これが明示的なmove
なしで行われるのはなぜですか?
をし、それが文字列を返します。したがって、String値はクロージャ環境から移動されるため、最初に移動する必要があります。これは基本的にここのコンパイラの理由ですか? –
@ JonasTepeは右のように聞こえます。クロージャー内のある関数/メソッド呼び出しのために値によって使用されていた場合にも移動されていました。 – Shepmaster