Quand une fermeture met-elle en œuvre Fn, FnMut et FnOnce?

114

Quelles sont les conditions spécifiques d'une fermeture pour implémenter les traits Fn, FnMutet FnOnce?

C'est:

  • Quand une fermeture ne met-elle pas en œuvre le FnOncetrait?
  • Quand une fermeture ne met-elle pas en œuvre le FnMuttrait?
  • Quand une fermeture ne met-elle pas en œuvre le Fntrait?

Par exemple, la mutation de l'état de la fermeture sur son corps empêche le compilateur de l'implémenter Fn.

Denilson Amorim
la source
11
Avez-vous vu cet article récent sur les fermetures ?
Shepmaster

Réponses:

126

Les traits représentent chacun des propriétés de plus en plus restrictives sur les fermetures / fonctions, indiquées par les signatures de leur call_...méthode, et notamment le type de self:

  • FnOnce( self) sont des fonctions qui peuvent être appelées une fois
  • FnMut( &mut self) sont des fonctions qui peuvent être appelées si elles ont &mutaccès à leur environnement
  • Fn( &self) sont des fonctions qui peuvent être appelées si elles n'ont &accès qu'à leur environnement

Une fermeture |...| ...implémentera automatiquement autant de ceux-ci que possible.

  • Toutes les fermetures implémentent FnOnce: une fermeture qui ne peut pas être appelée une fois ne mérite pas ce nom. Notez que si une fermeture n'est implémentée que FnOnce, elle ne peut être appelée qu'une seule fois.
  • Les fermetures qui ne sortent pas de leurs captures implémentent FnMut, ce qui leur permet d'être appelées plus d'une fois (s'il y a un accès sans alias à l'objet fonction).
  • Les fermetures qui n'ont pas besoin d'un accès unique / modifiable à leurs captures implémentent Fn, ce qui leur permet d'être appelées pratiquement partout.

Ces restrictions découlent directement du type selfet du "désugarage" des fermetures en structures; décrit dans mon article de blog Finding Closure in Rust .

Pour plus d'informations sur les fermetures, consultez Fermetures: fonctions anonymes pouvant capturer leur environnement dans le langage de programmation Rust .

huon
la source
Si une fermeture n'implémente que FnOnce, cela signifie-t-il qu'elle ne peut être appelée qu'une seule fois?
nalply
@nalply, oui, une seule fois.
huon
9
J'ai mal lu le commentaire de nalply et cela m'a causé une certaine confusion. Futurs lecteurs, veuillez noter qu'il a dit "si une fermeture ne met en œuvre que FnOnce".
sleeparrow
2
Détails de mise en œuvre: implémentera automatiquement autant de ceux-ci que possible. n'est pas entièrement vrai, il les implémentera automatiquement si cela semble nécessaire. Vous pouvez détecter un Fn-impl manquant pour une fermeture qui a été utilisée pour un argument FnMut à l'aide de la spécialisation. C'est le bogue github.com/rust-lang/rust/issues/26085
bluss le