Génériques Rust expressifs avec la clause where

Beginner

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

Introduction

Dans ce laboratoire, nous apprenons qu'une clause where en Rust peut être utilisée pour exprimer des contraintes pour les types génériques séparément de leur déclaration, permettant une syntaxe plus claire, et peut également appliquer des contraintes à des types arbitraires plutôt que seulement aux paramètres de type. La clause where est particulièrement utile lorsque les contraintes sont plus expressives que la syntaxe normale, comme dans l'exemple impliquant le trait PrintInOption.

Note : Si le laboratoire ne spécifie pas de nom de fichier, 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.

Clauses where

Une contrainte peut également être exprimée en utilisant une clause where immédiatement avant l'ouverture {, plutôt qu'au premier usage du type. De plus, les clauses where peuvent appliquer des contraintes à des types arbitraires, plutôt qu'à seulement des paramètres de type.

Certains cas où une clause where est utile :

  • Lorsque la spécification séparée des types génériques et des contraintes est plus claire :
impl <A: TraitB + TraitC, D: TraitE + TraitF> MyTrait<A, D> for YourType {}

// Expression des contraintes avec une clause `where`
impl <A, D> MyTrait<A, D> for YourType where
    A: TraitB + TraitC,
    D: TraitE + TraitF {}
  • Lorsque l'utilisation d'une clause where est plus expressive que l'utilisation de la syntaxe normale. L'impl dans cet exemple ne peut pas être directement exprimé sans une clause where :
use std::fmt::Debug;

trait PrintInOption {
    fn print_in_option(self);
}

// Car sinon, nous devrions l'exprimer comme `T: Debug` ou
// utiliser une autre méthode d'approche indirecte, ce qui nécessite une clause `where` :
impl<T> PrintInOption for T where
    Option<T>: Debug {
    // Nous voulons `Option<T>: Debug` comme contrainte car c'est ce qui est
    // affiché. Faire autrement serait utiliser la mauvaise contrainte.
    fn print_in_option(self) {
        println!("{:?}", Some(self));
    }
}

fn main() {
    let vec = vec![1, 2, 3];

    vec.print_in_option();
}

Résumé

Félicitations! Vous avez terminé le laboratoire sur les clauses where. Vous pouvez pratiquer d'autres laboratoires sur LabEx pour améliorer vos compétences.