J'ai essayé le code suivant:
fn main() {
let v2 = vec![1; 10];
println!("{}", v2);
}
Mais le compilateur se plaint:
error[E0277]: `std::vec::Vec<{integer}>` doesn't implement `std::fmt::Display`
--> src/main.rs:3:20
|
3 | println!("{}", v2);
| ^^ `std::vec::Vec<{integer}>` cannot be formatted with the default formatter
|
= help: the trait `std::fmt::Display` is not implemented for `std::vec::Vec<{integer}>`
= note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
= note: required by `std::fmt::Display::fmt`
Est-ce que quelqu'un implémente ce trait pour Vec<T>
?
Est-ce que quelqu'un implémente ce trait pour
Vec<T>
?
Non.
Et étonnamment, c'est une réponse manifestement correcte; ce qui est rare car prouver l'absence de choses est généralement difficile voire impossible. Alors, comment pouvons-nous être si certains?
La rouille a des règles de cohérence très strictes, le impl Trait for Struct
ne peut être fait que:
Trait
Struct
et nulle part ailleurs; nous allons essayez-le :
impl<T> std::fmt::Display for Vec<T> {
fn fmt(&self, _: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
Ok(())
}
}
rendements:
error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`)
--> src/main.rs:1:1
|
1 | impl<T> std::fmt::Display for Vec<T> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type
|
= note: only traits defined in the current crate can be implemented for a type parameter
De plus, pour utiliser un trait, il doit être dans la portée (et donc, vous devez être lié à sa caisse), ce qui signifie que:
Display
et à la caisse de Vec
Display
pour Vec
et nous amène donc à conclure que personne n'implémente Display
pour Vec
.
Comme solution de contournement, comme indiqué par Manishearth, vous pouvez utiliser le trait Debug
, qui est invocable via "{:?}"
comme spécificateur de format.
let v2 = vec![1; 10];
println!("{:?}", v2);
{}
est pour les chaînes et autres valeurs qui peuvent être affichées directement pour l'utilisateur. Il n'y a pas de moyen unique de montrer un vecteur à un utilisateur.
Le {:?}
le formateur peut être utilisé pour le déboguer, et il ressemblera à:
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
Display
est le trait qui fournit la méthode derrière {}
et Debug
est pour {:?}
Si vous connaissez le type des éléments que contient le vecteur, vous pouvez créer une structure qui prend le vecteur comme argument et implémenter Display
pour cette structure.
use std::fmt::{Display, Formatter, Error};
struct NumVec(Vec<u32>);
impl Display for NumVec {
fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
let mut comma_separated = String::new();
for num in &self.0[0..self.0.len() - 1] {
comma_separated.Push_str(&num.to_string());
comma_separated.Push_str(", ");
}
comma_separated.Push_str(&self.0[self.0.len() - 1].to_string());
write!(f, "{}", comma_separated)
}
}
fn main() {
let numbers = NumVec(vec![1; 10]);
println!("{}", numbers);
}
Voici un one-liner qui devrait également fonctionner pour vous:
println!("[{}]", v2.iter().fold(String::new(), |acc, &num| acc + &num.to_string() + ", "));
Ici est un exemple exécutable.
Dans mon propre cas, je recevais un Vec<&str>
D'un appel de fonction. Je ne voulais pas changer la signature de la fonction en un type personnalisé (pour lequel je pouvais implémenter le trait Display
).
Pour mon cas unique, j'ai pu transformer l'affichage de mon Vec
en un seul revêtement que j'ai utilisé avec println!()
directement comme suit:
println!("{}", myStrVec.iter().fold(String::new(), |acc, &arg| acc + arg));
(Le lambda peut être adapté pour être utilisé avec différents types de données ou pour des implémentations de traits Display
plus concises.)