クロージャを受け取る関数

クロージャが周辺の環境から変数を取得するやり方は非常に明瞭です。何か注意すべき点はあるのでしょうか? もちろんです。関数内でクロージャを使う場合、[ジェネリック]型を使用する必要があります。詳しく見ていきましょう。

#![allow(unused)] fn main() { // `F` must be generic. // `F` はジェネリック型でなくてはならない fn apply<F>(f: F) where F: FnOnce() { f(); } }

クロージャが定義されると、コンパイラは裏側で、無名の構造体を作り、そこにクロージャによって使用される外側の変数を入れます。同時にFnFnMutFnOnceという名のトレイトのいずれか一つを介してこの構造体に関数としての機能を実装し、実際に呼び出されるまで待ちます。

この無名構造体は型が未指定(unknown)なため、関数を実行する際にはジェネリクスが必要とされます。とはいえ、<T>で指定するだけでは、まだ曖昧です。(訳注: &self&mut selfselfのいずれをとるのかがわからないため)そのため、FnFnMutFnOnceのいずれか一つを実装することで対応しています。

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

参照

A thorough analysis, Fn, FnMut, and FnOnce