Difference between using macro `vec!` and method `to_vec`

Sorry if this question has already been done before (as I guess it is quite basic), but surprisingly I have not found it. What is the difference between the following two statements, and when should I use either one?

``````let x = vec![1, 2, 3];
let y = [1, 2, 3].to_vec();
``````

I would also like to ask, since for `String` there are both `to_string` and `String::from`, why for `Vec` there is just `to_vec` and not `Vec::from`.

Thanks

You can always check the documentation for `vec!`, click the `[src]` link and look at the definition:

``````macro_rules! vec {
(\$elem:expr; \$n:expr) => (
\$crate::vec::from_elem(\$elem, \$n)
);
(\$(\$x:expr),*) => (
<[_]>::into_vec(box [\$(\$x),*])
);
(\$(\$x:expr,)*) => (vec![\$(\$x),*])
}
``````

So `vec!` uses `<[_]>::into_vec`, not `<[_]>::to_vec`. If you look at the signatures, `to_vec` requires `T: Clone`, so `into_vec` is strictly more broadly useful.

Use whichever one you want. If one is faster, it's probably `vec!`, but unless you're constructing huge vectors as literals it probably won't matter much.

As for your assertion that there's no `Vec::from`: there's eleven of them, including one for slices.

1 Like

Oh, I hadn't noticed the `into_vec` part in the `vec!` definition, now I see the difference between `vec!` and `to_vec`. However, what is the reason for having `to_vec` silently cloning? Wouldn't it be better to have `to_vec` behave like `to_string`, and then have the user explicitly cloning only when necessary? This way `vec!` wouldn't even be needed, correct?

Regarding `Vec::from` could you please provide an example on how to use it to convert an array or slice into a `Vec`? (I'm not sure what I'm doing wrong here...)

Thanks again

I don't follow the question. `to_string` allocates a new `String`.

I corrected my last message to remove the allocation part which was obviously wrong. However, looking at the signatures of `to_vec` and `to_string` I understand that the former implicitly clones, while the latter doesn't, is it correct?

``````pub fn to_vec(&self) -> Vec<T>
where
T: Clone,`
``````
``````fn to_string(&self) -> String
``````

The description says for `to_vec` "Copies `self` into a new `Vec`" and for `to_string` "Converts the given value to a `String`", which is similar to `into_vec`'s description "Converts `self` into a vector without clones or allocation". So do I understand correctly that `to_string` behaves similarly to `into_vec`, while `to_vec` behaves differently? (by cloning)

Sorry for my questions, but I'm coming back to Rust after many years of not using it, and I feel a little rusty...

`to_string` has a different description, but, for `<&str>::to_string` at least, it's doing the same operation. `<&[u32]>::to_vec` clones each `u32` and allocates a new `Vec` to hold the cloned values. `<&str>::to_string` clones each `u8` holding the string data inside the string and allocates a new `String` to hold the cloned values.

Note that as both of these are "to" operations, the original data is still usable after doing things.

`into_vec` is different because it doesn't operate on `&[u32]`, but rather `Box<[u32]>`- something already allocated on the heap. It's an "into" operation because it is completely consuming the `Box<[u32]>` and transforming it into a `Vec<u32>`. It isn't doing any allocation, but at the same time the original `Box<[u32]>` is not usable.

The description for `to_string` is such because it's also usable for types other than `&str`. But in all cases it creates a new string and does not consume the original value. This is why it's a "to" operation not an "into" operation.

`to_string` comes from the `ToString` trait: ToString in std::string - Rust

Where you can see that its blanket implementation (the one you'll usually be using) is in terms of the `Display` trait: Display in std::fmt - Rust

So `x.to_string()` is almost always just `format!("{}", x)`, and thus rather different from something doing cloning.

It's different from cloning, but it is still more similar to `to_vec` than `into_vec`, just because both `to_string` and `to_vec` are "to" operations and allow someone to continue using the original data.

Can you please provide an example on how to use `Vec::from` to convert an array or slice into a `Vec`?

Also I would like to ask if there is the equivalent of `vec!` for `String` (something to create a `String` consuming the original `&str`).

``````let s: &[&str] = &["a", "b"];
let v = Vec::from(s);``````

What do you mean by consuming the original? Since itâ€™s a borrow you wouldnâ€™t consume it, at least in how the term "consume" is typically used.

There are many ways to create a `String` - are you only interested in a `&str` case?

Following your example, I now see that for instance the following code works:

``````let s: &[_] = &[1, 2];
let v = Vec::from(s);
``````

What I attempted before was:

``````let s = &[1, 2];
let v = Vec::from(s);
``````

Can you please explain why this one instead does not work? Doesn't Rust infer the same type `&[T]` for variable `s` in both cases?

As for my second question, if I understand correctly with `into_vec` the original vector is moved, so it is consumed by `into_vec`, meaning that it is not available anymore afterwards (I hope I'm expressing myself correctly). In other words, after calling `into_vec` there is only one memory region allocated to store the `Vec`. I wonder why there are no equivalent `str!` macro and `into_string` method to convert a `&str` into a `String` while consuming the original `&str`.

The type there becomes `&[i32;2]`, a reference to a 2 element array. It doesnâ€™t coerce it to a slice unless thatâ€™s what you ask for (or you use the array in a place where automatic deref coercion takes place).

`into_vec` consumes a `Box<[T]>`, not a Vec. Youâ€™re right that no extra allocations or copies are done here; this is accomplished by having the Vec take ownership of the heap allocation that the Box had already done.

`&str` doesnâ€™t own the allocation, unlike a Box, so thereâ€™s nothing to consume; you can copy the content into a new String, but original is left intact and owned by someone else. The analogous to the above is str - Rust.