0

Rust newbie here. I'm trying to write a function which consumes the passed vector, modifies it, appends it to another vector and returns it.

Here is my code:

fn try(other: Vec<(String, String)>) -> Vec<(String, String)> {
    let mut res = Vec::new();
    let mut neg: Vec<(String,String)> = other
                                        .iter()
                                        .map(|t| (t.0, String::from("abc")))
                                        .collect();
    res.append(&mut neg);
    res
}

However, I'm getting a cannot move out borrowed content at t.0. What is it that I'm doing wrong? What's getting passed into the closure?

pd176
  • 821
  • 3
  • 10
  • 20
  • `.iter()` returns an iterator to references of each element in the vector. You seem to want `into_iter()`. – E_net4 Apr 08 '19 at 12:44
  • What's the point of `res`? Why not just return `neg` directly? – Mara Bos Apr 08 '19 at 12:49
  • @E_net4 I wouldn't call that question a duplicate. That question you link you would only ask if you already know that you should use `into_iter` here. The answer to the question is quite relevant though. (Also, the best solution here is actually not to use `into_iter` at all, but just modify the original vector and return it.) – Mara Bos Apr 08 '19 at 12:53
  • 1
    @M-ou-se It's the answer that really matters when choosing a duplicate target. A question being a duplicate does not mean that the target question is exactly the same, but that its answers also address that problem. As for whether it's a good duplicate target or not, I'll leave the decision to the remaining voters. – E_net4 Apr 08 '19 at 12:55
  • thanks a lot. i agree with the comments. it was a matter of knowing that into_iter was to be used in this context. – pd176 Apr 08 '19 at 13:05

1 Answers1

1

t.0 tries to move the String out of the tuple that t refers to, but t only borrows it. That's because .iter() gives you an iterator that gives you references to the values. If you use into_iter() instead of iter() you get to consume all the values of other, instead of only getting to borrow them, because other.into_iter() consumes other.

In your specific example, it would be more efficient to completely re-use other instead of creating a new Vec with the contents (partially) taken from other, and then dropping other:

fn try2(mut other: Vec<(String, String)>) -> Vec<(String, String)> {
    for x in &mut other {
        x.1 = String::from("abc");
    }
    other
}

It could be even more efficient to re-use the Strings as well, instead of creating new ones with String::from.

Mara Bos
  • 955
  • 5
  • 11
  • How does your answer differ from the suggested duplicate [What is the difference between iter and into_iter?](https://stackoverflow.com/questions/34733811/what-is-the-difference-between-iter-and-into-iter)? – hellow Apr 08 '19 at 12:53
  • @hellow That question only handles the first part. Showing that `into_iter()` and `collect()` is not the best option in this case is quite a relevant part that is not handled in that question/answer. – Mara Bos Apr 08 '19 at 13:01