I'm writing a function that will transfer the contents from one Vec
to another.
I managed to write two different versions of the same code. One is cleaner, but is potentially slower.
Version 1:
fn move_values<T>(buffer: &mut Vec<T>, recipient: &mut Vec<T>) {
loop {
let value = buffer.pop();
if value.is_none() {
return;
}
recipient.push(value.unwrap());
}
}
Version 2:
fn move_values<T>(buffer: &mut Vec<T>, recipient: &mut Vec<T>) {
for value in buffer.iter() {
recipient.push(value.clone());
}
buffer.clear();
}
My initial gut feeling is that Version 1 is faster because it only requires a single run through the buffer; while Version 2 is more "Rusty" because it involves iterating over a collection rather than using loop
.
Which of these is more idiomatic or "better practice" in general?
Note, I'm aware of append
, I'm trying to do this by hand for educational purposes.
Neither. There's a built-in operation for this,
Vec::append
:Neither of your functions even compile:
Well, there's a reason that it's implemented for you, but sure... let's dig in.
Checking if something
is_some
oris_none
can usually be avoided by pattern matching. For example:Of course, this moves everything in reverse order because pushing and popping to a Vec both occur at the end.
Calling
clone
doesn't do what you want unless your trait bounds say thatT
implementsClone
. Otherwise, you are just cloning the reference itself.You can avoid the need for cloning if you drain the values from one collection and insert them into the other:
But that
for
loop is silly, justextend
the collection using the iterator:I'd still use the built in
append
method to do this when transferring between collections of the same type, as it is probably optimized for the precise data layout, and potentially specialized for certain types of data.