Wann implementiert ein Abschluss Fn, FnMut und FnOnce?

114

Was sind die besonderen Bedingungen für eine Schließung der zu implementieren Fn, FnMutund FnOnceZüge?

Das ist:

  • Wann setzt eine Schließung das Merkmal nicht um FnOnce?
  • Wann setzt eine Schließung das Merkmal nicht um FnMut?
  • Wann setzt eine Schließung das Merkmal nicht um Fn?

Wenn Sie beispielsweise den Status des Abschlusses auf seinem Body ändern, wird der Compiler nicht darauf implementiert Fn.

Denilson Amorim
quelle
11
Haben Sie diesen kürzlich erschienenen großartigen Artikel über Schließungen gesehen ?
Shepmaster

Antworten:

126

Die Merkmale repräsentieren jeweils immer restriktivere Eigenschaften von Verschlüssen / Funktionen, die durch die Signaturen ihrer call_...Methode und insbesondere die Art von self:

  • FnOnce( self) sind Funktionen, die einmal aufgerufen werden können
  • FnMut( &mut self) sind Funktionen, die aufgerufen werden können, wenn sie &mutZugriff auf ihre Umgebung haben
  • Fn( &self) sind Funktionen, die aufgerufen werden können, wenn sie nur &Zugriff auf ihre Umgebung haben

Ein Abschluss |...| ...implementiert automatisch so viele davon wie möglich.

  • Alle Verschlüsse implementieren FnOnce: Ein Verschluss, der nicht einmal aufgerufen werden kann, verdient den Namen nicht. Beachten Sie, dass ein Abschluss, der nur implementiert wird FnOnce, nur einmal aufgerufen werden kann.
  • Verschlüsse, die nicht aus ihren Captures entfernt werden, werden implementiert FnMut, sodass sie mehrmals aufgerufen werden können (wenn ein unvoreingenommener Zugriff auf das Funktionsobjekt besteht).
  • Verschlüsse, die keinen eindeutigen / veränderlichen Zugriff auf ihre Captures benötigen, werden implementiert Fn, sodass sie im Wesentlichen überall aufgerufen werden können.

Diese Einschränkungen ergeben sich direkt aus der Art selfund dem "Desugaring" von Verschlüssen in Strukturen; beschrieben in meinem Blog-Beitrag Finding Closure in Rust .

Informationen zu Schließungen finden Sie unter Schließungen : Anonyme Funktionen, die ihre Umgebung in der Programmiersprache Rust erfassen können .

huon
quelle
Wenn ein Abschluss nur implementiert wird FnOnce, bedeutet dies, dass er nur einmal aufgerufen werden kann?
Nalply
@nalply, ja, nur einmal.
Huon
9
Ich habe den Kommentar von nalply falsch verstanden und es hat mich verwirrt. Zukünftige Leser, bitte beachten Sie, dass er sagte "wenn eine Schließung nur implementiert FnOnce".
Schlafpfeil
2
Implementierungsdetail: Implementiert automatisch so viele davon wie möglich. ist nicht ganz richtig, es wird sie automatisch implementieren, wenn es benötigt wird. Sie können ein fehlendes Fn-Impl für einen Abschluss erkennen, der für ein FnMut-Argument mithilfe der Spezialisierung verwendet wurde. Dies ist Fehler github.com/rust-lang/rust/issues/26085
Bluss