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