C'est l'équivalent de l'utilisation des itérateurs :
pub fn foo(text: &str, string: &str) -> Vec<L> {
text.lines()
.enumerate()
.flat_map(|(x, line)| {
line.match_indices(string).map(move |(y, _)| { L { x, y } })
})
.collect()
}
Démonté ligne par ligne :
.enumerate()
enumerate
est utilisé pour transformer un itérateur de T
en un itérateur de (usize, T)
ce qui revient à compresser la valeur originale avec l'indice. Vous faites cela parce que vous gardez la trace du numéro de ligne avec la fonction x
.
.flat_map(|(x, line)| { ... })
flat_map
est utilisé pour permettre à chaque valeur de l'itérateur de retourner son propre itérateur dont les valeurs sont ensuite aplaties en un seul flux.
line.match_indices(string).map(move |(y, _)| { L { x, y } })
Ici, nous utilisons simplement map
pour prendre le x
et le y
et créer un L
. move
est utilisé car sinon x
sera emprunté pour la fermeture, mais l'itérateur et la fermeture sont renvoyés à l'utilisateur. flat_map
fermeture, vivant plus longtemps que x
. Le site move
ne fait que copier le x
donc ce n'est pas un problème.
.collect()
collect
est utilisé pour convertir un itérateur en quelque chose qui peut être fait à partir de l'itérateur en mettant en œuvre la fonction FromIterator
généralement des collections comme Vec
. Cette méthode utilise également l'inférence de type en sachant que nous retournons un fichier Vec<L>
il sait qu'il faut collecter dans un Vec<L>
.
Vous pouvez vérifier l'équivalence sur le Rust Playground
.