How to print a Vec?

RustPrintln

Rust Problem Overview


I tried the following code:

fn main() {
    let v2 = vec![1; 10];
    println!("{}", v2);
}

But the compiler complains:

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`

Does anyone implement this trait for Vec<T>?

Rust Solutions


Solution 1 - Rust

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.

The {:?} formatter 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 {:?}

Solution 2 - Rust

> Does anyone implement this trait for Vec<T> ?

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>`)
 --> 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

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.

Solution 3 - Rust

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);
}

Solution 4 - Rust

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.)

Solution 5 - Rust

Starting with Rust 1.58, there is a slightly more concise way to print a vector (or anything else). This lets you put the variable you want to print inside the curly braces, instead of needing to put it at the end. For the debug formatting needed to print a vector, you add :? in the braces, like this:

fn main() {
    let v2 = vec![1; 10];
    println!("{v2:?}");
}

Solution 6 - Rust

Is there any reason not to write the vector's content item by item w/o former collecting? *)

use std::fmt::{Display, Formatter, Error};

struct NumVec(Vec<u32>);

impl Display for NumVec {
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
        let v = &self.0;
        if v.len() == 0 {
            return Ok(());
        }
        for num in &v[0..v.len() - 1] {
            if let Err(e) = write!(f, "{}, ", &num.to_string()) {
                return Err(e);
            }
        }
        write!(f, "{}", &v[v.len() - 1])
    }
}

fn main() {
    let numbers = NumVec(vec![1; 10]);
    println!("{}", numbers);
}

*) No there isn't.

Because we want to display something, the Display trait is implemented for sure. So this is correct Rust because: the Doc says about the ToString trait:

"This trait is automatically implemented for any type which implements the Display trait. As such, ToString shouldn’t be implemented directly: Display should be implemented instead, and you get the ToString implementation for free."

In particular on microcontrollers where space is limited I definitely would go with this solution and write immediately.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionhighfly22View Question on Stackoverflow
Solution 1 - RustManishearthView Answer on Stackoverflow
Solution 2 - RustMatthieu M.View Answer on Stackoverflow
Solution 3 - RusteviloneView Answer on Stackoverflow
Solution 4 - RustU007DView Answer on Stackoverflow
Solution 5 - RustDaniel GigerView Answer on Stackoverflow
Solution 6 - RustKaplanView Answer on Stackoverflow