Pour comprendre la fonction collect, il est important de savoir qu'elle sert à résoudre un itérateur. Rappelons qu'un itérateur est une séquence d'éléments que l'on peut enchaîner avec d'autres itérateurs. Les itérateurs sont paresseux, ce qui signifie qu'ils ne s'exécutent pas tant qu'on n'appelle pas du code qui consomme l'itérateur. Parmi ce code, on trouve les boucles for et les adaptateurs consommateurs. Les adaptateurs consommateurs traitent tous les éléments de l'itérateur pour produire une sorte de résultat.
collect est l'un de ces adaptateurs consommateurs, et il peut servir à produire une instance de n'importe quel type qui implémente le trait FromIterator. Ce trait est implémenté pour toutes les collections de la bibliothèque standard. Comme FromIterator est implémenté pour de nombreux types, il faut indiquer à Rust le type de collection que l'on souhaite. Par exemple, si on veut un Vec<char> à partir d'une tranche de chaîne de caractères, on peut préciser le type dans l'appel à collect, comme ceci :
let my_chars = "Hello, World!".chars().collect::<Vec<char>>();
// since the item type of the `String::chars()` iterator can be inferred to be `char`, we can omit that information
// let my_chars = "Hello, World!".chars().collect::<Vec<_>>();
Les doubles deux-points et les chevrons extérieurs (c'est-à-dire ::<_>) sont appelés le turbofish. Ici, le turbofish est une syntaxe plus lourde que nécessaire. En précisant le type directement sur la liaison, collect peut déduire quelle collection créer, avec une syntaxe moins lourde.
let my_chars: Vec<char> = "Hello, World!".chars().collect();
// or
// let my_chars: Vec<_> = "Hello, World!".chars().collect();
Si on voulait une String dont les caractères sont inversés, on pourrait faire comme ceci :
let rev_chars: String = "Hello, World!".chars().rev().collect();
L'inférence de type de Rust est suffisamment puissante pour que, parfois, on n'ait pas besoin de préciser le type explicitement :
fn get_reversed_chars(phrase: &str) -> Vec<char> {
phrase.chars().rev().collect()
}
Le type de retour de la fonction get_reversed_chars permet à collect de déduire quelle collection renvoyer. Ici, en revanche, il faut préciser Vec<char> et non Vec<_>, car Rust n'effectue pas d'inférence de type pour les signatures de fonctions. C'est pour que la personne qui lit le code sache rapidement quels types une fonction consomme et renvoie.