Reputation: 135
This may be a silly question, but it tackled me.
I've started learning rust, from the allmighty book. In the iterator chapter (the one linked therein) there's the following example
fn iterator_demonstration() {
let v1 = vec![1, 2, 3];
let mut v1_iter = v1.iter();
assert_eq!(v1_iter.next(), Some(&1));
assert_eq!(v1_iter.next(), Some(&2));
assert_eq!(v1_iter.next(), Some(&3));
assert_eq!(v1_iter.next(), None);
}
The book kinda glazed over it, but I wonder - why are the ampersands needed?
edit: just to clarify - I do understand iter
iterates through immutable references. I just don't quite grasp referencing a numeric literal (again, rookie question.)
Upvotes: 6
Views: 332
Reputation: 58975
Because they're pointers. Follow the docs.
v1
is a Vec<i32>
. So T
is i32
.Vec
doesn't have an iter
method. It does Deref
to [T]
. Scroll down further.[T]
has an iter
method. It returns a std::slice::Iter<T>
.v1_iter
is an Iter<i32>
, so T
is i32
.next
is part of the Iterator
trait, so scroll down and look for the impl Iterator
section.next
returns an Option<&'a T>
. Substitute T
, and that gives you Option<&'a i32>
.Pre-emptive: Why are they pointers?
Because that's what you asked for. If you wanted to move the contents of the Vec
out via an iterator, you need to use Vec::into_iter
or Vec::drain
.
Upvotes: 7
Reputation: 5305
The function Vec::iter()
is of type (self :&Vec<T>) -> Q<&T>
. That is, it creates an iterator of some type Q
that isn't important here, that iterates over references to the T
elements in your Vec
. It uses an immutable reference to the Vec
, so it doesn't take any elements out or have any effect on the Vec
at all.
All Iterator
s have a cloned()
method that turns an iterator over &T
references into an iterator over T
values, so long as T
has the Clone
trait. It wraps the other iterator in a little bit of code that calls the clone()
method on all the references to the elements, turning them into new T
s.
fn iterator_demonstration() {
let v1 = vec![1, 2, 3];
let mut v1_iter = v1.iter().cloned();
assert_eq!(v1_iter.next(), Some(1));
assert_eq!(v1_iter.next(), Some(2));
assert_eq!(v1_iter.next(), Some(3));
assert_eq!(v1_iter.next(), None);
}
Vec
also implements IntoIterator
, which consumes the Vec
into an iterator over T
, takes all the T
in the Vec
and passes them back. It destroys the Vec
and takes ownership of all its T
values. You can use the into_iter()
method to explicitly use it, and it's also used in for loops.
fn iterator_demonstration2() {
let v1 = vec![1, 2, 3];
let mut v1_iter = v1.into_iter();
assert_eq!(v1_iter.next(), Some(1));
assert_eq!(v1_iter.next(), Some(2));
assert_eq!(v1_iter.next(), Some(3));
assert_eq!(v1_iter.next(), None);
}
fn iterator_demonstration3() {
let v1 = vec![1, 2, 3];
for i in v1 {
println!("{}", i);
}
}
Upvotes: 1