Fermetures Rust avec contraintes de type générique

RustRustBeginner
Pratiquer maintenant

This tutorial is from open-source community. Access the source code

💡 Ce tutoriel est traduit par l'IA à partir de la version anglaise. Pour voir la version originale, vous pouvez cliquer ici

Introduction

Dans ce laboratoire, il est expliqué que les closures en Rust utilisent l'anonymat de type, ce qui nécessite l'utilisation de types génériques lorsqu'on utilise des closures comme paramètres de fonction.

Note : Si le nom de fichier n'est pas spécifié dans le laboratoire, vous pouvez utiliser n'importe quel nom de fichier que vous voulez. Par exemple, vous pouvez utiliser main.rs, le compiler et l'exécuter avec rustc main.rs &&./main.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL rust(("Rust")) -.-> rust/BasicConceptsGroup(["Basic Concepts"]) rust(("Rust")) -.-> rust/FunctionsandClosuresGroup(["Functions and Closures"]) rust(("Rust")) -.-> rust/AdvancedTopicsGroup(["Advanced Topics"]) rust/BasicConceptsGroup -.-> rust/variable_declarations("Variable Declarations") rust/FunctionsandClosuresGroup -.-> rust/function_syntax("Function Syntax") rust/FunctionsandClosuresGroup -.-> rust/expressions_statements("Expressions and Statements") rust/AdvancedTopicsGroup -.-> rust/operator_overloading("Traits for Operator Overloading") subgraph Lab Skills rust/variable_declarations -.-> lab-99325{{"Fermetures Rust avec contraintes de type générique"}} rust/function_syntax -.-> lab-99325{{"Fermetures Rust avec contraintes de type générique"}} rust/expressions_statements -.-> lab-99325{{"Fermetures Rust avec contraintes de type générique"}} rust/operator_overloading -.-> lab-99325{{"Fermetures Rust avec contraintes de type générique"}} end

Anonymat de type

Les closures capturent succinctement les variables des portées entourantes. Est-ce que cela a des conséquences? C'est certainement le cas. Observez comment utiliser une closure comme paramètre de fonction nécessite des [types génériques], ce qui est nécessaire en raison de la manière dont elles sont définies :

// `F` doit être générique.
fn apply<F>(f: F) where
    F: FnOnce() {
    f();
}

Lorsqu'une closure est définie, le compilateur crée implicitement une nouvelle structure anonyme pour stocker les variables capturées à l'intérieur, tout en implémentant la fonctionnalité via l'un des traits : Fn, FnMut ou FnOnce pour ce type inconnu. Ce type est assigné à la variable qui est stockée jusqu'à l'appel.

Puisque ce nouveau type est de type inconnu, toute utilisation dans une fonction nécessitera des types génériques. Cependant, un paramètre de type non borné <T> serait toujours ambigu et ne serait pas autorisé. Ainsi, être limité par l'un des traits : Fn, FnMut ou FnOnce (qu'il implémente) est suffisant pour spécifier son type.

// `F` doit implémenter `Fn` pour une closure qui ne prend
// pas d'entrées et ne renvoie rien - exactement ce qui est
// requis pour `print`.
fn apply<F>(f: F) where
    F: Fn() {
    f();
}

fn main() {
    let x = 7;

    // Capture `x` dans un type anonyme et implémente
    // `Fn` pour lui. Stocke-le dans `print`.
    let print = || println!("{}", x);

    apply(print);
}

Sommaire

Félicitations! Vous avez terminé le laboratoire Anonymat de type. Vous pouvez pratiquer d'autres laboratoires dans LabEx pour améliorer vos compétences.