Comment itérer et filtrer un tableau?

J’essaie d’écrire un programme qui implique le filtrage et le pliage des tableaux. J’ai utilisé The Rust Programming Language , première édition comme référence, mais je ne comprends pas ce qui se passe lorsque je forme des iterators sur des tableaux. Voici un exemple:

fn comstacks() { let range = (1..6); let range_iter = range.into_iter(); range_iter.filter(|&x| x == 2); } fn does_not_comstack() { let array = [1, 4, 3, 2, 2]; let array_iter = array.into_iter(); //13:34 error: the trait `core::cmp::PartialEq` is not implemented for the type `&_` [E0277] array_iter.filter(|&x| x == 2); } fn janky_workaround() { let array = [1, 4, 3, 2, 2]; let array_iter = array.into_iter(); // Note the dereference in the lambda body array_iter.filter(|&x| *x == 2); } 

( Rust aire de jeux )

Dans la première fonction, je suis que l’iterator sur la plage ne prend pas possession, donc je dois prendre un &x dans le filter lambda, mais je ne comprends pas pourquoi le deuxième exemple avec le tableau se comporte différemment.

Dans de tels cas, il est très utile de forcer le compilateur à vous indiquer le type de la variable. Déclenchons une erreur de type en affectant l’argument de fermeture à un type incompatible:

 array_iter.filter(|x| { let () = x; true }); 

Cela échoue avec:

 error[E0308]: mismatched types --> src/main.rs:12:33 | 12 | array_iter.filter(|x| { let () = x; true }); | ^^ expected &&{integer}, found () | = note: expected type `&&{integer}` found type `()` 

Maintenant, nous soaps que le type de x est un &&{integer} – une référence à une référence à un type entier. Nous pouvons alors nous comparer à cela:

 fn hooray() { let array = [1, 4, 3, 2, 2]; let array_iter = array.into_iter(); array_iter.filter(|&&x| x == 2); } 

La question devient maintenant “pourquoi est-ce une référence à une référence”? La version courte est que l’ iterator d’un tableau renvoie des références (voir le type Item = &'a T partie). De plus, Iterator::filter transmet une référence à la fermeture pour éviter de se déplacer et de perdre ensuite des types non- Copy .

Les tableaux sont du type [T; N] [T; N] dans Rust, pour n’importe quel type d’élément T et un nombre constant N C’est un tableau de taille fixe.

Rust n’implémente pas d’iterators de valeur pour les tableaux pour le moment. Tous les tableaux contraignent aux tranches (type [T] ) et les méthodes de tranche sont disponibles sur le tableau à cause de cela. Les tableaux ont aussi l’iterator de la tranche, appelé std::slice::Iter<'a, T> et a des éléments de type &'a T : itère par référence!

C’est pourquoi into_iter() sur une Range produit un iterator de into_iter() et into_iter() sur un [i32; 5] [i32; 5] produit un iterator de &i32 .

Si vous avez besoin d’iterators de valeur pour les tableaux, ils ont été implémentés dans l’écosystème plus large, voir (1) et (2) .

Comme Shepmaster et Bluss l’a dit, vous pouvez vérifier la documentation du type de tableau , qui mentionne:

Les tableaux de tailles de 0 à 32 (inclus) implémentent les traits suivants si le type d’élément le permet:

  • IntoIterator (implémenté pour &[T; N] et &mut [T; N] )

Comme il est dit, ceci ne concerne que les références et se reflète dans son type Item : type Item = &'a T et type Item = &'a mut T