クロージャーはいつFn、FnMut、FnOnceを実装しますか?


114

クロージャーが、およびトレイトを実装するための特定の条件は何ですか?FnFnMutFnOnce

あれは:

  • クロージャーいつFnOnceトレイトを実装しないのですか?
  • クロージャーいつFnMutトレイトを実装しないのですか?
  • クロージャーいつFnトレイトを実装しないのですか?

たとえば、本体のクロージャの状態を変更すると、コンパイラはそのクロージャを実装Fnしなくなります。


11
クロージャーに関するこの最近の素晴らしい記事を見ましたか?
Shepmaster

回答:


126

トレイトはそれぞれ、call_...メソッドのシグネチャ、特に次のタイプによって示される、クロージャ/関数に関するますます制限的なプロパティを表しますself

  • FnOnceself)は一度だけ呼び出すことができる関数です
  • FnMut&mut self&mut環境にアクセスできる場合に呼び出すことができる関数
  • Fn&self)は&、環境へのアクセス権がある場合にのみ呼び出すことができる関数です

クロージャー|...| ...はそれらを可能な限り自動的に実装します。

  • すべてのクロージャーが実装しFnOnceます。一度呼び出すことができないクロージャーは名前に値しません。クロージャーが実装FnOnceするのは1回だけであることに注意してください。
  • キャプチャの外に移動しないFnMutクロージャーは、それらを複数回呼び出せるようにします(関数オブジェクトへのエイリアスのないアクセスがある場合)。
  • キャプチャの実装への一意で可変のアクセスを必要としないクロージャは、Fn本質的にどこからでも呼び出せるようにします。

これらの制限はself、クロージャのタイプと構造体への「脱糖化」から直接従います。私のブログ記事「Frusting Closure in Rust」で説明されています。

クロージャの詳細については、「クロージャ:Rustプログラミング言語の環境キャプチャできる無名関数」を参照してください。


クロージャがを実装するだけの場合、FnOnceこれは一度しか呼び出せないということですか?
-nalply

@nalply、はい、一度だけ。
2015年

9
nalplyのコメントを読み間違えたため、混乱が生じました。今後の読者は、「クロージャ実装する場合のみ」と言ったことに注意してくださいFnOnce
sleeparrow

2
実装の詳細:可能な限り多くのものを自動的に実装します。完全に正しいわけではなく、必要と思われる場合は自動的に実装されます。特殊化を使用して、FnMut引数に使用されたクロージャーの欠落しているFn-implを検出できます。これはバグgithub.com/rust-lang/rust/issues/26085
bluss
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.