# Can I borrow the Moved Iterator?

The concept of **Ownership** is no doubt one of [Rust](https://www.rust-lang.org/)'s most unique feature. I recently worked on a [command line program](https://charlesmuchene.com/rusty-crates-in-the-cargo) using Rust and encountered a scenario where I couldn't get *Ownership* right. In this article, we discuss a similar scenario and my solution.

## Scenario

Say we are required to print all the numbers in a given range. But before printing the last number, output "*I knew it was &lt;last-number&gt;!*".

```rust
fn print_em(numbers: Range<u32>) {
    let last = numbers.end;
    for number in numbers {
        if number == last {
            println!("I knew last was {}!", number);
        }
        println!("{number}");
    }
}
```

Straightforward! The requirements are changed such that we're given an `Iterator` instead of a `Range`. A possible refactor would look like the following:

```rust
fn print_em(numbers: impl Iterator<Item=u32>) {
    let last = numbers.last().expect("No last number");
    for number in numbers {
        if number == last {
            println!("I knew last was {}!", number);
        }
        println!("{number}");
    }
}
```

In this snippet, we change the type of the parameter to an `impl Iterator<Item=u32>` i.e. any type that implements the `Iterator` trait with an associated type of `u32`.

---

Our program, however, fails to compile after this change. To determine the last value, we call `numbers.last()`. This call [**moves**](https://doc.rust-lang.org/book/ch04-01-what-is-ownership.html#variables-and-data-interacting-with-move) `numbers` because we have to *consume* the iterator to reach the *last* number. `numbers` is then invalidated and we cannot use it again. This move is highlighted by the compiler as shown below:

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1680801624780/dfd8cdbd-75b9-43e1-ac21-5b955df7e58e.png align="center")

Is there another way to determine the last item in an iterator without consuming it?

## A Peekable approach

Checking the docs, we find [`Peekable`](https://doc.rust-lang.org/std/iter/struct.Peekable.html) - an iterator that wraps another iterator. `Peekable` provides a `peek()` method that will return an optional reference to the `next()` value without advancing the iterator. Hmm. Promising.

Using a `Peekable` while inside an iteration, we can `peek()` and inspect the optional. If it is the `None` variant, then we are in the last iteration. Perfect!

```rust
fn print_em(numbers: impl Iterator<Item=u32>) {
    let mut peekable = numbers.peekable();
    for number in peekable {
        if let None = peekable.peek() {
            println!("I knew last was {}!", number);
        }
        println!("{number}");
    }
}
```

Refactor. Save. `cargo check`. Bam! 🤯

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1680803677285/e36171e5-20dc-4233-9f8a-497dec0a9b0f.png align="center")

What now? Another move? Well, I suppose these are common gotchas in Rust. Let's take a closer look at the note in the compiler output:

> `into_iter` takes ownership of the receiver `self`, which moves `peekable`

Back in the [docs](https://doc.rust-lang.org/std/iter/index.html#for-loops-and-intoiterator), we look for `into_iter()`. We learn that in the standard library, all `Iterator`s implement the [`IntoIterator`](https://doc.rust-lang.org/std/iter/trait.IntoIterator.html) trait and just return themselves. Also, when using a *for loop*, some de-sugaring happens at compile time for implementations of `IntoIterator` i.e. `peekable::into_iter()` is called and that moves our `peekable`!

Recap: we can take a peek into the future but our iterator is consumed by the de-sugar magic. We, therefore, need to get around this *move* or avoid it altogether. So, what's our next move? 😎

## Change the loop structure

Rust has three kinds of loops:

* `for` - loop over an iterator -- *not suitable for our situation* 🙅🏾‍♂️
    
* `loop` - loop forever until we stop it -- *a possible solution* 🤷🏾‍♂️
    
* `while` - loop while a condition is true -- *a better solution* 🙋🏾‍♂️
    

Using a `while` loop syntax, we can [pattern-match](https://doc.rust-lang.org/book/ch18-00-patterns.html) the `peekable.next()` and bind the value to `number` in each iteration. With this change, we can iterate over our `numbers` and `peek()` to determine if the current number is the last one. Mission accomplished!

```rust
fn print_em(numbers: impl Iterator<Item=u32>) {
    let mut peekable = numbers.peekable();
    while let Some(number) = peekable.next() {
        if let None = peekable.peek() {
            println!("I knew last was {}!", number);
        }
        println!("{number}");
    }
}
```

The code above is safe, consumes the iterator once and adapts to an iterator of any given number of elements. Bam! 🥳

## Conclusion

Rust, like any language, takes some getting used to. Learning the gotchas, the standard library and, generally, getting a hang of things in an ecosystem. What better way to learn anything than by doing it?

Tip: when working on a project, have a browser tab open at [https://doc.rust-lang.org/std/index.html](https://doc.rust-lang.org/std/index.html). Searching works like a charm and the docs are even more charming!

Happy coding!
