Printing Vec in Rust: From Beginner to Pro

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

"How do I print a Vec?" — a question every Rust developer has asked

\n\n

If you've ever written in Rust and tried to simply print a vector to the screen, you've likely encountered this:

\n\n
fn main() {\n    let numbers = vec![1, 2, 3, 4, 5];\n    println!("{}", numbers); // Error!\n}
\n\n

The compiler greets you with a red message: `Vec<{integer}>` doesn't implement `std::fmt::Display`. Sound familiar? This question on Stack Overflow has gathered thousands of views, and for good reason. In Rust, there's no "magic" — the compiler requires you to specify how exactly you want to display the collection. And that's great, because it gives you full control.

\n\n

In this article, we'll cover all the main ways to print a Vec in Rust: from quick debug output to creating beautiful formatting for the user. You'll learn which method to use when, and stop being afraid of compilation errors.

\n\n

Why doesn't Vec implement Display?

\n\n

Before jumping into the code, let's understand Rust's philosophy. The Display trait is intended for displaying data to the user — the way you want to see it in the interface. And Debug is for debugging and logs.

\n\n

For a vector, it's impossible to guess which format you need:

\n
    \n
  • Print elements separated by commas?
  • \n
  • Each element on a new line?
  • \n
  • In square brackets, like an array?
  • \n
  • Or as a table?
  • \n
\n\n

That's why Rust developers decided not to impose a single format, but to leave the choice to the programmer. Let's look at what options we have.

\n\n

Method 1: Quick Debug Output (Debug)

\n\n

The simplest way is to use {:?} or {:#?} (pretty-print). For this, the element type of the vector must implement the Debug trait.

\n\n
fn main() {\n    let numbers = vec![1, 2, 3, 4, 5];\n    println!("{:?}", numbers);    // [1, 2, 3, 4, 5]\n    println!("{:#?}", numbers);   // Pretty output:\n                                  // [\n                                  //     1,\n                                  //     2,\n                                  //     3,\n                                  //     4,\n                                  //     5\n                                  // ]\n}
\n\n

When to use: debugging, logging, quick checks. Usually not suitable for production — the format is inflexible.

\n\n

Important: if your type doesn't implement Debug, the compiler will tell you. For your own structs, you can add #[derive(Debug)]:

\n\n
#[derive(Debug)]\nstruct Point {\n    x: f64,\n    y: f64,\n}\n\nfn main() {\n    let points = vec![Point { x: 1.0, y: 2.0 }, Point { x: 3.0, y: 4.0 }];\n    println!("{:?}", points);\n}
\n\n

Method 2: Manual Iteration with an Iterator

\n\n

The most flexible way is to write your own loop. You get full control over the format.

\n\n
fn main() {\n    let words = vec!["hello", "world", "rust"];\n    \n    // Option 1: comma-separated\n    for (i, word) in words.iter().enumerate() {\n        if i > 0 {\n            print!(", ");\n        }\n        print!("{}", word);\n    }\n    println!(); // hello, world, rust\n\n    // Option 2: each on a new line\n    for word in &words {\n        println!("- {}", word);\n    }\n    // - hello\n    // - world\n    // - rust\n}
\n\n

This approach gives maximum flexibility but requires more code. Great for when you need unique formatting.

\n\n

Method 3: Using an Iterator with collect and join

\n\n

If you simply need to join elements into a string, you can use join from the SliceConcatExt trait (available for slices):

\n\n
fn main() {\n    let words = vec!["hello", "world", "rust"];\n    let joined = words.join(", ");\n    println!("{}", joined); //                

Blogs

Book Recommendations