Skip to content

Commit

Permalink
chore(content/til): add "2024_02_07-iter_vs_into__iter"
Browse files Browse the repository at this point in the history
  • Loading branch information
mateusfg7 authored Feb 7, 2024
1 parent c41ab7c commit e776a57
Showing 1 changed file with 85 additions and 0 deletions.
85 changes: 85 additions & 0 deletions content/til/2024_02_07-iter_vs_into__iter.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
---
title: '`iter` vs `into_iter`'
description: 'Tthe difference between `iter`, `into_iter` and `iter_mut` on Rust'
date: '2024-02-07'
tags: [rust,iterators]
---

**TL;DR**

- The iterator returned by `into_iter` may yield any of `T`, `&T` or `&mut T`, depending on the context.
- The iterator returned by `iter` will yield `&T`, by convention.
- The iterator returned by iter_mut will yield &mut T, by convention.

---

The first question is: "What is `into_iter`?"

`into_iter` comes from the [`IntoIterator` trait](https://doc.rust-lang.org/std/iter/trait.IntoIterator.html):

```rust
pub trait IntoIterator
where
<Self::IntoIter as Iterator>::Item == Self::Item,
{
type Item;
type IntoIter: Iterator;
fn into_iter(self) -> Self::IntoIter;
}
```

You implement this trait when you want to specify how a particular type is to be converted into an iterator. Most notably, if a type implements `IntoIterator` it can be used in a `for` loop.

For example, `Vec` implements `IntoIterator`... thrice!

```rust
impl<T> IntoIterator for Vec<T>
impl<'a, T> IntoIterator for &'a Vec<T>
impl<'a, T> IntoIterator for &'a mut Vec<T>
```

Each variant is slightly different.

This one consumes the `Vec` and its iterator [yields **values**](https://doc.rust-lang.org/std/vec/struct.Vec.html#impl-IntoIterator) (`T` directly):

```rust
impl<T> IntoIterator for Vec<T> {
type Item = T;
type IntoIter = IntoIter<T>;

fn into_iter(mut self) -> IntoIter<T> { /* ... */ }
}
```

The other two take the vector by reference (don't be fooled by the signature of `into_iter(self)` because `self` is a reference in both cases) and their iterators will produce references to the elements inside `Vec`.

This one [yields **immutable references**](https://doc.rust-lang.org/std/vec/struct.Vec.html#impl-IntoIterator-1):

```rust
impl<'a, T> IntoIterator for &'a Vec<T> {
type Item = &'a T;
type IntoIter = slice::Iter<'a, T>;

fn into_iter(self) -> slice::Iter<'a, T> { /* ... */ }
}
```

While this one [yields **mutable references**](https://doc.rust-lang.org/std/vec/struct.Vec.html#impl-IntoIterator-2):

```rust
impl<'a, T> IntoIterator for &'a mut Vec<T> {
type Item = &'a mut T;
type IntoIter = slice::IterMut<'a, T>;

fn into_iter(self) -> slice::IterMut<'a, T> { /* ... */ }
}
```

---

So:
> What is the difference between `iter` and `into_iter`?
`into_iter` is a generic method to obtain an iterator, whether this iterator yields values, immutable references or mutable references **is context dependent** and can sometimes be surprising.

`iter` and `iter_mut` are ad-hoc methods. Their return type is therefore independent of the context, and will conventionally be iterators yielding immutable references and mutable references, respectively.

0 comments on commit e776a57

Please sign in to comment.