I am reading the Rust 101 tutorial, where the author talks about shared borrowing with the example of a Vec object passed to a function. Below is a slightly adapted MWE of what the the tutorial is teaching. The interesting part is v.iter() in vec_min. The author writes:
This time, we explicitly request an iterator for the vector
v. The methoditerborrows the vector it works on, and provides shared borrows of the elements.
But what happens if I use a for ... in ... construction on an object which is shared? According to this blog post, this implicit for loop uses into_iter(), taking ownership of v. But it cannot really take ownership of the v in that function, since it has only borrowed it to begin with, right?
Can somebody explain the difference between into_iter() and iter() applied to a borrowed object to me?
enum NumberOrNothing {
Number(i32),
Nothing,
}
use self::NumberOrNothing::{Number,Nothing};
impl NumberOrNothing {
fn print(self) {
match self {
Nothing => println!("The number is: <nothing>"),
Number(n) => println!("The number is: {}", n),
};
}
}
fn vec_min(v: &Vec<i32>) -> NumberOrNothing {
fn min_i32(a: i32, b: i32) -> i32 {
if a < b {a} else {b}
}
let mut min = Nothing;
for e in v.iter() {
//Alternatively implicitly and with *e replaced by e:
//for e in v {
min = Number(match min {
Nothing => *e,
Number(n) => min_i32(n, *e),
});
}
min
}
pub fn main() {
let vec = vec![18,5,7,2,9,27];
let foo = Nothing;
let min = vec_min(&vec);
let min = vec_min(&vec);
min.print();
}
There isn't a difference.
it cannot really take ownership of the
vin that function, since it has only borrowed it to begin with
It absolutely can take ownership of v, because that's a &Vec. Note the precise semantics here - you are taking ownership of the reference, not of the referred-to item.
If you check out the implementors of IntoIterator, you can find:
impl<'a, T> IntoIterator for &'a Vec<T>
And the source for that:
impl<'a, T, A: Allocator> IntoIterator for &'a Vec<T, A> {
type Item = &'a T;
type IntoIter = slice::Iter<'a, T>;
fn into_iter(self) -> slice::Iter<'a, T> {
self.iter()
}
}
Surprise — it calls iter!
The same logic applies for &mut vec and vec.iter_mut()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With