Is it possible to take ownership of data back from a for loop once the loop completes


#1

I am just getting started with Rust and am quickly falling in love with it.

I love the concept of ownership and borrowing but am unsure of how this applies to for loops in all contexts.

I have found a bunch of information on for loops in Rust and how they map to this construct under the hood

let mut it = values.into_iter();
loop {
    match it.next() {
        Some(x) => println!("{}", x),
        None => break,
    }
}

They move their values by default (into_iter), and I understand you can use a borrow (reference) instead like so:

for v in &mut vec {
    ....
}

or

for v in vec.iter_mut() {
    ....
}

but what I’m curious about is as with a function where you can take ownership, and then return it to the caller, is there a way of doing this in a for loop in Rust, or must you always use a borrow. Essentially is there any way of getting ownership back from a for loop?

Thank you very much for your time and help!

All the best,

Tom


#2

I don’t think there’s strictly a way of getting back ownership. If you could, the Vec would be empty when it was returned from the for loop anyway (unless you break before the end maybe?), so it would be pretty much like using drain. Is there a specific use case you’re looking for, or is drain good enough?


#3

Not specific to loops, but if you give up ownership, you’re done with the object you give up. For example, let’s say that I have an owned identity function:

fn<T> id(t: T) -> T { t }

When you call this function, you move your T (whatever T is) into the function (unless your type is Copy, in which case you could be making a copy). At the end of the function you again move the T back to the caller.

Now if you wanted to do that with a loop, you’d need a way to return the original object from the loop, however, you’ve already moved the object into its .into_iter() method. Even the iterator object that method returns is given to the loop. So unless your value is Copy, it’s gone.


#4

Ah okay I see, so then I guess I don’t understand the context in which you would use a for loop without using the container or array as a reference. When would you want the behaviour you describe?

Thank you for the explanations! Very helpful!


#5

As an example, if I write this

for v in vec {
    println!("{}", v);
}

followed immediately by…

for v in vec {
    println!("{}", v);
}

…again, then I get this ‘error: use of moved value: vec’

Which I understand, but then does this mean you should only really use a for loop with a borrow, so &vec, not vec.

Thanks again!


#6

I recommend checking out my Rustcamp talk on this problem: http://cglab.ca/~abeinges/talks/iter/#0

Basically there’s 4 kinds of iteration:

iter, iter_mut, into_iter, and drain. Each has different tradeoffs for what you want to do with both the data and the container. Usually, iterating by-reference is the goto, because destructive iteration is really heavy-handed for most problems (but is useful when you need it!).


#7

Sweet I’ll check out the link, thank you!