Day25:iter & into_iter & the confusion - 100DayOfRust
Tags: rust
Published: 2019-12-13 17:36:52

Yep, I came back to `iter` and `into_iter` again after 2 previous post. In [one of the previous post](https://dev.to/0xbf/day22-iter-map-foreach-filter-closure-100dayofrust-1cgi) I thought I already understood them: `iter` return referencer, `into_iter` return value, until I saw this:

```rust
fn main() {
    let v1 = vec![1,2,3];
    let v2 = [1,2,3];

    println!("{}", v1.into_iter().any(|x| x == 2));
    println!("{}", v2.into_iter().any(|x| *x == 2)); 
}
```

Well I got why the closure for `v1.into_iter` use `x` directly, because `into_iter` return value, but why v2's `into_iter` returned a reference?

After spending time on searching it, I found the [answer here in stackoverflow](https://stackoverflow.com/questions/34733811/what-is-the-difference-between-iter-and-into-iter), the `v2.into_iter` actually is not calling `into_iter` on the array itself, it is applied to a reference to v2:

> 1. IntoIterator is not implemented for [T; N], only for &[T; N] and &mut [T; N]
> 2. When a method is not implemented for a value, it is automatically searched for references to that value instead

Also in the [Rust doc here](https://doc.rust-lang.org/std/primitive.array.html), it mentioned:

> IntoIterator (implemented for &[T; N] and &mut [T; N])

Ok, so this v2.into_iter is actually (&v2).into_iter, if we change the code to:

```rust
println!("{}", (&v2).into_iter().any(|x| *x == 2)); 
```

It works the same because Rust tries to find the `into_iter` on `v2`, but it cannot find it, so it searches this method on `&v2`, then it works. That's also why it yields a reference type as x in our closure.

So far so good, let's see another example: according to Rust's document: [Rust's for loop syntax is actually sugar for iterators](https://doc.rust-lang.org/stable/std/iter/index.html#for-loops-and-intoiterator)

So if we have code like this:
```rust
let values = vec![1, 2, 3];

for x in values {
    println!("{}", x);
}
```

It is the same as:
```rust
let v1 = vec![1, 2, 3];

for x in v1.into_iter() {
    println!("{}", x);
}
```

This works well, now let's try it on our array v2:
```rust
fn main() {
    let v1 = vec![1,2,3];
    let v2 = [1,2,3];


    for i in v1 {
        println!("{}", i);
    }
    
    for i in v2 {
        println!("{}", i);
    }
}
```

This will give us a compile error!

```
10 |     for i in v2 {
   |              ^^ borrow the array with `&` or call `.iter()` on it to iterate over it
``` 

Wait, if `for i in v2` is the same as `for i in v2.into_iter()` and we know `v2.into_iter()` will be converted to `(&v2).into_iter()`, shouldn't this work? why this time Rust asks us to explicitly use `&v2`?

If we use code like this:
```rust
for i in &v2 {
    println!("{}", i);
}
```

It works and makes sense, because it will change to `for i in (&v2).into_iter()`

or if we change code to this:
```rust
for i in v2.into_iter() {
    println!("{}", i);
}
```

It would work too! Because now it found the `into_iter` method is on &v2, and actually calling `(&v2).into_iter()`

So `for i in something` is sometimes the same as `for i in something.into_iter()`, sometimes is not, which is so confusing.

Rust is known being strict on type and compiling, but this cause confusion when this code works:

```rust
println!("{}", v2.into_iter().any(|x| *x == 2)); 
```

I'd rather Rust reported an error and force using `&v2` like this:

```rust
println!("{}", (&v2).into_iter().any(|x| *x == 2)); 
```

If it forces using in this way, then we would know `for i in v2` won't work, we will write code `for i in &v2` and we would know it equals to `for i in (&v2).into_iter()`.


When v2 is an array, the way `for i in v2` doesn't work, but `for i in v2.into_iter()` and `for i in &v2` works, is just confusing.