はじめに
この実験では、クロージャについて調べます。クロージャは、Rust の関数で、そのスコープ外の変数を参照することで囲まれた環境をキャプチャできます。
注: 実験でファイル名が指定されていない場合は、好きなファイル名を使用できます。たとえば、
main.rsを使用して、rustc main.rs &&./mainでコンパイルして実行できます。
クロージャ
クロージャは、囲まれた環境をキャプチャできる関数です。たとえば、x 変数をキャプチャするクロージャは次のようになります。
|val| val + x
クロージャの構文と機能は、即座の使用にとても便利です。クロージャを呼び出すことは、関数を呼び出すのとまったく同じです。ただし、入力型と戻り値の型は 推論できる 場合があり、入力変数名は _指定する必要があります_。
クロージャの他の特徴としては、次のものが挙げられます。
- 入力変数の周りに
()の代わりに||を使用すること。 - 単一の式の場合のオプショナルな本体の区切り (
{})(それ以外の場合は必須)。 - 外側の環境変数をキャプチャする能力。
fn main() {
let outer_var = 42;
// 通常の関数は、囲まれた環境の変数を参照できません
//fn function(i: i32) -> i32 { i + outer_var }
// TODO: 上の行のコメントを外して、コンパイラエラーを確認してください。コンパイラは、代わりにクロージャを定義するように提案します。
// クロージャは匿名で、ここではそれらを参照にバインドしています
// アノテーションは関数のアノテーションと同じですが、オプショナルです
// 本体を囲む `{}` も同様です。これらの名前のない関数は、適切な名前の変数に割り当てられます。
let closure_annotated = |i: i32| -> i32 { i + outer_var };
let closure_inferred = |i | i + outer_var ;
// クロージャを呼び出します。
println!("closure_annotated: {}", closure_annotated(1));
println!("closure_inferred: {}", closure_inferred(1));
// クロージャの型が推論された後は、別の型で再度推論することはできません。
//println!("cannot reuse closure_inferred with another type: {}", closure_inferred(42i64));
// TODO: 上の行のコメントを外して、コンパイラエラーを確認してください。
// 引数を持たない `i32` を返すクロージャ。
// 戻り値の型は推論されます。
let one = || 1;
println!("closure returning one: {}", one());
}
まとめ
おめでとうございます!クロージャの実験を完了しました。スキルを向上させるために、LabEx でさらに多くの実験を行って練習してください。