avshyz
avshyz

Reputation: 135

Iterator's next returns Some(&1). Why's that?

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

Answers (2)

DK.
DK.

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.
  • Just below, it specifies that 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

NovaDenizen
NovaDenizen

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 Iterators 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 Ts.

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

Related Questions