I've been working my way through the book Rust in Action and i've seen The generic syntax Vec<T>
where T is any type in my understanding but also i've seen Vec<_>
which I read that infers the type based off of the contents of the vector. I was wondering what the distinction between Vec<T>
and Vec<_>
is because I can't tell the difference between them as they appear to do the same thing? Or their descriptions would seem to lead me to believe. Why would I use one vs the other?

- 614
- 1
- 6
- 20
-
https://stackoverflow.com/questions/34363984/what-is-vec – E_net4 Dec 13 '21 at 16:52
2 Answers
The _
is called a wildcard. It basically tells Rust to just deduce the type needed, and that's it.
For Vec<T>
it's a generic it does two things, it names the type, but also is a generic parameter for any type. Since you don't know what type it can be, you use T
to tell in places where it should be that type, where to get the information from (in a sense).
So _
means any type, but deduced in context (a unique type), T
is a generic type, and can be many types (a new generation is done for each separate type it encounters).

- 2,411
- 1
- 19
- 24
Vec<T>
could be defined as (the actual definition is more complex):
pub struct Vec<T> {
buf: RawVec<T>,
len: usize,
}
As such, it's called Vec<T>
because that's how the generic struct is defined.
When creating a Vec
, you have to specify what the type of the elements are:
let x: Vec<u8> = vec![1, 2, 3];
Here, the type annotation isn't actually needed, since the compiler can infer it for us.
Let's say we want to obtain all of the command line arguments as a Vec
. We could try:
let args = std::env::args().collect();
...but that fails with:
error[E0282]: type annotations needed
--> src/main.rs:2:9
|
2 | let args = std::env::args().collect();
| ^^^^ consider giving `args` a type
since we didn't specify which container to collect the arguments into: .collect()
can collect the iterator elements into a Vec<T>
, a Box<[T]>
, a LinkedList<T>
, and many more. Let's specify a type:
let args: Vec<String> = std::env::args().collect();
This compiles, but we can make this a bit simpler: we can do
let args: Vec<_> = std::env::args().collect();
and get the same effect, since the _
tells the compiler to infer what the type is. Since there is only one possible type inferred by the compiler, it replaces the _
with String
. Vec<_>
isn't a type, it's a partial type that makes the compiler fill in the _
.

- 4,770
- 2
- 20
- 53