Points clés
- Les fermetures Rust sont des fonctions anonymes qui peuvent capturer des variables de leur portée environnante, permettant des modèles de programmation fonctionnelle puissants.
- Le langage propose trois types de fermetures distincts — Fn, FnMut et FnOnce — chacun défini par la manière dont ils interagissent avec les variables d'environnement capturées.
- Les fermetures infèrent automatiquement les types de paramètres et de retour à partir du contexte, bien que des annotations explicites puissent être fournies si nécessaire pour plus de clarté.
- Le mot-clé move force les fermetures à prendre possession des variables capturées, les rendant adaptées aux contextes multithread et garantissant la validité des données.
- Les fermetures sont largement utilisées avec les itérateurs Rust, permettant une transformation concise des données grâce à des méthodes comme map, filter et fold.
Résumé rapide
Les fermetures de Rust représentent l'une des fonctionnalités les plus puissantes et flexibles du langage, permettant aux développeurs d'écrire du code concis et expressif qui capture et manipule des données de son environnement. Contrairement aux fonctions traditionnelles, les fermetures peuvent accéder aux variables de leur portée englobante, ce qui les rend idéales pour les rappels, les itérateurs et les modèles de programmation fonctionnelle.
Ce guide explore les concepts fondamentaux des fermetures Rust, de leur syntaxe de base aux mécanismes avancés de possession. En comprenant comment les fermetures interagissent avec le système de possession de Rust, les développeurs peuvent écrire du code plus sûr et plus efficace tout en évitant les pièges courants liés à la gestion de la mémoire et à l'emprunt.
La syntaxe des fermetures
Les fermetures Rust utilisent une syntaxe propre et intuitive qui ressemble à une définition de fonction mais avec des différences clés. Une fermeture est définie à l'aide de barres verticales | | pour encadrer ses paramètres, suivies d'une expression ou d'un bloc contenant sa logique. Cette syntaxe compacte rend les fermetures idéales pour une utilisation en ligne, notamment avec les méthodes d'itérateur.
Par exemple, une fermeture qui double un nombre peut être écrite comme |x| x * 2. Cette brièveté est l'une des philosophies de conception de Rust — les fermetures doivent être faciles à écrire et à lire. Contrairement aux fonctions régulières, les fermetures ne nécessitent pas d'annotations de type explicites pour les paramètres ou les valeurs de retour, car le compilateur les infère à partir du contexte.
Cependant, lorsque le compilateur ne peut pas inférer les types, les développeurs peuvent les spécifier explicitement. Par exemple, |x: i32| x * 2 clarifie que l'entrée est un entier 32 bits. Cette flexibilité permet aux fermetures de s'adapter à divers contextes tout en maintenant la sécurité de type stricte de Rust.
La véritable puissance des fermetures émerge lorsqu'elles capturent des variables de leur environnement. Considérez cet exemple :
- Une fermeture qui ajoute une valeur constante à son entrée
- Elle capture la constante de la portée environnante
- La fermeture peut être réutilisée avec différentes entrées
- Elle conserve l'accès à la variable capturée
Propriété et emprunt
Les fermetures interagissent avec le système de possession de Rust de manière nuancée, déterminant si elles déplacent ou empruntent les variables capturées. Ce comportement est régi par l'implémentation de la fermeture et la manière dont elle utilise les données capturées. Comprendre ces règles est essentiel pour écrire du code correct et efficace.
Lorsqu'une fermeture prend possession d'une variable, elle déplace la valeur dans la fermeture, rendant la variable d'origine indisponible par la suite. Cela se produit généralement lorsque la fermeture doit posséder les données pour garantir qu'elles restent valides. Inversement, si la fermeture n'emprunte que la variable, l'originale reste accessible en dehors de la fermeture.
Le compilateur détermine automatiquement s'il faut déplacer ou emprunter en fonction de la manière dont la fermeture utilise la variable capturée. Si la fermeture ne fait que lire la variable, elle l'emprunte. Si elle doit stocker la variable ou la retourner, elle la déplace. Cette inférence automatique simplifie le développement tout en maintenant la sécurité de la mémoire.
Les développeurs peuvent contrôler explicitement ce comportement en utilisant le mot-clé move avant la liste de paramètres de la fermeture. Cela force la fermeture à prendre possession de toutes les variables capturées, ce qui est particulièrement utile lors du passage de fermetures à des threads ou pour garantir que les données vivent suffisamment longtemps.
Le mot-clé move garantit que les variables capturées sont possédées par la fermeture, empêchant les références pendantes et rendant les fermetures sécurisées pour les threads.
Types de fermetures 🎯
Rust catégorise les fermetures en trois types distincts en fonction de la manière dont elles interagissent avec les variables capturées : Fn, FnMut et FnOnce. Chaque trait représente un niveau d'accès et de possession différent, permettant au compilateur d'optimiser et d'appliquer des garanties de sécurité.
Le trait Fn représente les fermetures qui n'empruntent que les variables capturées immuablement. Ces fermetures peuvent être appelées plusieurs fois sans consommer les données capturées. Elles sont idéales pour les opérations en lecture seule, telles que le filtrage ou le mappage de collections.
Les fermetures FnMut, d'autre part, peuvent muter les variables capturées. Elles empruntent les données de manière mutable, permettant des modifications de l'environnement. Ce type est utile pour les opérations qui nécessitent une mise à jour de l'état, telles que l'accumulation de valeurs ou la modification de variables externes.
Le trait FnOnce s'applique aux fermetures qui consomment les variables capturées. Ces fermetures ne peuvent être appelées qu'une seule fois car elles prennent possession des données. Ce type est nécessaire lorsque la fermeture doit retourner ou stocker la variable capturée, garantissant que les données ne sont pas utilisées après l'exécution de la fermeture.
Lors de l'implémentation de ces traits, le compilateur sélectionne automatiquement le plus approprié en fonction du comportement de la fermeture. Ce processus de sélection garantit que les fermetures sont aussi flexibles que possible tout en maintenant des règles de sécurité strictes.
- Fn : Emprunts immuables, appels multiples possibles
- FnMut : Emprunts mutables, appels multiples possibles
- FnOnce : Prend possession, appel unique possible
Applications pratiques
Les fermetures excellent en programmation Rust réelle, notamment lorsqu'on travaille avec des itérateurs et des rappels. Leur capacité à capturer des variables d'environnement les rend indispensables pour écrire du code concis et lisible qui effectue des opérations complexes.
Les itérateurs sont un exemple typique de fermetures en action. Des méthodes comme map, filter et fold acceptent des fermetures pour transformer ou traiter des collections. Par exemple, l'utilisation de map avec une fermeture permet aux développeurs d'appliquer une fonction à chaque élément d'une collection sans écrire de boucles explicites.
Les rappels sont un autre cas d'usage courant. Dans la programmation asynchrone ou les systèmes pilotés par les événements, les fermetures fournissent un moyen de définir un comportement qui s'exécute en réponse à des événements spécifiques. Leur capacité à capturer le contexte les rend idéales pour gérer des opérations avec état.
De plus, les fermetures permettent des modèles de programmation fonctionnelle dans Rust. En composant des fermetures, les développeurs peuvent créer des pipelines d'opérations qui sont à la fois efficaces et expressifs. Cette approche réduit le code de sertissage et améliore la maintenabilité.
Considérez ces scénarios pratiques où les fermetures excellent :
- Transformation des données dans une collection avec
map - Filtrage des éléments basé sur des conditions complexes
- Implémentation d'une logique de tri personnalisée
- Définition de gestionnaires d'événements dans des applications GUI
Points clés à retenir
Les fermetures Rust sont un outil polyvalent qui combine la puissance des fonctions anonymes










