可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I tried the following code:
let v2 = vec![1; 10];
println!("{}", v2);
But the compiler complains that:
error[E0277]: the trait bound `std::vec::Vec<{integer}>: std::fmt::Display` is not satisfied
--> src/main.rs:3:20
|
3 | println!("{}", v2);
| ^^ trait `std::vec::Vec<{integer}>: std::fmt::Display` not satisfied
|
= note: `std::vec::Vec<{integer}>` cannot be formatted with the default formatter; try using `:?` instead if you are using a format string
= note: required by `std::fmt::Display::fmt`
Does anyone implement this trait for Vec<T>
?
回答1:
Does anyone implement this trait for Vec<>
?
No.
And surprisingly, this is a demonstrably correct answer; which is rare since proving the absence of things is usually hard or impossible. So how can we be so certain?
Rust has very strict coherence rules, the impl Trait for Struct
can only be done:
- either in the same crate as
Trait
- or in the same crate as
Struct
and nowhere else; let's try it:
impl<T> std::fmt::Display for Vec<T> {
fn fmt(&self, _: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
Ok(())
}
}
yields:
error[E0210]: type parameter `T` must be used as the type parameter for some
local type (e.g. `MyStruct<T>`); only traits defined in the
current crate can be implemented for a type parameter
--> src/main.rs:1:1
|
1 | impl<T> std::fmt::Display for Vec<T> {
| ^
Furthermore, to use a trait
, it needs to be in scope (and therefore, you need to be linked to its crate), which means that:
- you are linked both with the crate of
Display
and the crate of Vec
- neither implement
Display
for Vec
and therefore leads us to conclude that no one implements Display
for Vec
.
As a work around, as indicated by Manishearth, you can use the Debug
trait, which is invokable via "{:?}"
as a format specifier.
回答2:
let v2 = vec![1; 10];
println!("{:?}", v2);
{}
is for strings and other values which can be displayed directly to the user. There's no single way to show a vector to a user, however {:?}
can be used to debug it, and it will look like:
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
Display
is the trait that provides the method behind {}
, and Debug
is for {:?}
回答3:
If you know the type of the elements that the vector contains, you could make a struct that takes vector as an argument and implement Display
for that struct.
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);
}
回答4:
Here is a one-liner which should also work for you:
println!("[{}]", v2.iter().fold(String::new(), |acc, &num| acc + &num.to_string() + ", "));
Here is
a runnable example.
In my own case, I was receiving a Vec<&str>
from a function call. I did not want to change the function signature to a custom type (for which I could implement the Display
trait).
For my one-of case, I was able to turn the display of my Vec
into a one-liner which I used with println!()
directly as follows:
println!("{}", myStrVec.iter().fold(String::new(), |acc, &arg| acc + arg));
(The lambda can be adapted for use with different data types, or for more concise Display
trait implementations.)