Passing a mutable versus Pass and return Vec<String>

I have this Vec (well it is a double-ended queue but for all intent and purpose, it should probably function as a vector) that I would like to alter:
let mut text_history:VecDeque<String>= VecDeque::new();

I have two options

  1. Pass its mutable reference:
fn append_history(text_history: &mut VecDeque<String>)  {
    text_history.push_back(format!("hello"));   
}
  1. Pass and return it, catch later:
fn append_history(text_history: & VecDeque<String>) ->VecDeque<String>  {
    let mut new_text_history= text_history.clone();
    new_text_history.push_back(format!("hello"));
    return new_text_history;   
}

And then

text_history=append_history(text_history);

So both work, and 1 is probably a more efficient way to do what I want but I think 2 will produce a more systematic/idiomatic code?

I am not sure. Which one do you recommend, or neither and I should go for something else?

There's nothing non-idiomatic about passing a &mut.

What I would say is that you generally shouldn't have a method that immediately clones an argument like that. If you need ownership, then have the caller pass you an owned value.

So the &mut version is fine, but if you prefer you could also do

fn append_history(mut text_history: VecDeque<String>) -> VecDeque<String>  {
    text_history.push_back(format!("hello"));
    text_history
}

EDIT: added the missing mut that's mentioned below.

3 Likes

Wait I am confused:

fn append_history(text_history: VecDeque<String>) -> VecDeque<String>  {
    text_history.push_back(format!("hello"));
    text_history
}

Shouldn't this result in an error like: Cannot borrow immutable local variable as mutable?

Yes, it should be mut text_history but that's all.

4 Likes