クロージャ
Rustにおけるクロージャは、その外側の環境を捕捉した関数のことです。例えば、次のコードは変数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());
}