From e776a57efdab75e79a61d75ccddfc9fbb28a58b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateus=20Felipe=20Gon=C3=A7alves?= <mateusfelipefg77@gmail.com> Date: Wed, 7 Feb 2024 11:18:25 -0300 Subject: [PATCH 1/2] chore(content/til): add "2024_02_07-iter_vs_into__iter" --- content/til/2024_02_07-iter_vs_into__iter.mdx | 85 +++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 content/til/2024_02_07-iter_vs_into__iter.mdx diff --git a/content/til/2024_02_07-iter_vs_into__iter.mdx b/content/til/2024_02_07-iter_vs_into__iter.mdx new file mode 100644 index 00000000..b6fa4178 --- /dev/null +++ b/content/til/2024_02_07-iter_vs_into__iter.mdx @@ -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. From 6a4bb877028091bd625e28b3b91d1635c8da8d25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateus=20Felipe=20Gon=C3=A7alves?= <mateusfelipefg77@gmail.com> Date: Wed, 7 Feb 2024 11:20:13 -0300 Subject: [PATCH 2/2] chore(content/til): update "2024_02_07-iter_vs_into__iter" --- content/til/2024_02_07-iter_vs_into__iter.mdx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/content/til/2024_02_07-iter_vs_into__iter.mdx b/content/til/2024_02_07-iter_vs_into__iter.mdx index b6fa4178..69ebbdf8 100644 --- a/content/til/2024_02_07-iter_vs_into__iter.mdx +++ b/content/til/2024_02_07-iter_vs_into__iter.mdx @@ -83,3 +83,5 @@ So: `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. + +**ref:** https://stackoverflow.com/a/34745885