Rust のクロージャと環境キャプチャの探索

Beginner

This tutorial is from open-source community. Access the source code

はじめに

この実験では、クロージャについて調べます。クロージャは、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 でさらに多くの実験を行って練習してください。