Kiedy zamknięcie implementuje Fn, FnMut i FnOnce?

114

Jakie są szczególne warunki dla zamknięcia do wdrożenia Fn, FnMutoraz FnOncecechy?

To jest:

  • Kiedy zamknięcie nie realizuje FnOncecechy?
  • Kiedy zamknięcie nie realizuje FnMutcechy?
  • Kiedy zamknięcie nie realizuje Fncechy?

Na przykład mutacja stanu zamknięcia w jego treści powoduje, że kompilator nie implementuje Fngo.

Denilson Amorim
źródło
11
Czy widziałeś ten ostatni wspaniały artykuł o zamknięciach ?
Shepmaster

Odpowiedzi:

126

Każda z cech reprezentuje coraz bardziej restrykcyjne właściwości dotyczące domknięć / funkcji, na które wskazują sygnatury ich call_...metody, a zwłaszcza rodzaj self:

  • FnOnce( self) to funkcje, które można wywołać raz
  • FnMut( &mut self) to funkcje, które można wywołać, jeśli mają &mutdostęp do swojego środowiska
  • Fn( &self) to funkcje, które można wywołać, jeśli mają &dostęp tylko do swojego środowiska

Zamknięcie |...| ...automatycznie zaimplementuje tak wiele z nich, jak to tylko możliwe.

  • Wszystkie zamknięcia implementują FnOnce: zamknięcie, którego nie można wywołać raz, nie zasługuje na tę nazwę. Zwróć uwagę, że jeśli zamknięcie działa tylko FnOnce, można je wywołać tylko raz.
  • Zamknięcia, które nie wychodzą z ich przechwytywania implementują FnMut, umożliwiając wywoływanie ich więcej niż raz (jeśli istnieje dostęp bez uprawnień do obiektu funkcji).
  • Zamknięcia, które nie wymagają unikalnego / zmiennego dostępu do ich implementacji przechwytywania Fn, dzięki czemu można je wywoływać praktycznie wszędzie.

Ograniczenia te wynikają bezpośrednio z rodzaju selfi „odcukrzenia” zamknięć w strukturach; opisane w moim wpisie na blogu Finding Closure in Rust .

Aby uzyskać informacje na temat domknięć, zobacz Zamknięcia: anonimowe funkcje, które mogą uchwycić swoje środowisko w języku programowania Rust .

huon
źródło
Jeśli zamknięcie działa tylko FnOnce, czy to oznacza, że ​​można je wywołać tylko raz?
nalply
@nalply, tak, tylko raz.
huon
9
Błędnie odczytałem komentarz nalply i spowodowało to pewne zamieszanie. Przyszli czytelnicy, proszę zauważyć, że powiedział „jeśli tylko zamknięcie realizuje FnOnce”.
sleeparrow
2
Szczegóły implementacji: automatycznie zaimplementuje jak najwięcej z nich. nie jest do końca prawdą, zaimplementuje je automatycznie, jeśli okaże się to konieczne. Możesz wykryć brakujący Fn-impl dla zamknięcia, które zostało użyte dla argumentu FnMut przy użyciu specjalizacji. To jest błąd github.com/rust-lang/rust/issues/26085
bluss