# Pre-RFC: Iterator::extend\_into

**URL:** <https://internals.rust-lang.org/t/pre-rfc-iterator-extend-into/6662>\
**Category:** libs\
**Created:** [January 27, 2018, 8:03pm UTC](https://internals.rust-lang.org/t/pre-rfc-iterator-extend-into/6662 "2018-01-27T20:03:28Z")\
**Posts on this page:** 18\
**Page:** 1

<div class="post-metadata">

**Author:** ![CodeSandwich](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/codesandwich/32/3479_2.png) [@CodeSandwich](https://internals.rust-lang.org/u/CodeSandwich)\
**Post date:** [January 27, 2018, 8:03pm UTC](https://internals.rust-lang.org/t/pre-rfc-iterator-extend-into/6662/1 "2018-01-27T20:03:28Z")

</div>

I’ve got an idea about improving `Iterator`. Since it came into my head I started noticing more and more places, where I wished I could use this. At first I didn’t find any trace of anybody proposing it, but somebody pointed me to this [Rust issue](https://github.com/rust-lang/rust/issues/45840#issuecomment-343346317), which is similar, but has different perspective. This was posted originally on [Rust users forum](https://users.rust-lang.org/t/pre-rfc-iterator-extend/15278/4). What do you think about this idea?

# Summary

Add `Iterator::extend_into` method, which takes a collection and extend it with iterator’s `self`.

# Motivation

Sometimes there is a need to create a sophisticated iterator and then put all it’s items into a collection. Of cource there is `Iterator::collect`, which creates a new collection, but there is no convenient method of collecting into an **EXISTING** one.

Sure, it’s possible, but a bit awkward:

```rust
fn my_fn(&self, vec: &mut Vec) {
    let iter = self.items.iter()
        .filter(...)
        .enumerate()
        .map(...);
    vec.extend(iter);
}

```

or more compact, but way harder to follow:

```rust
fn my_fn(&self, vec: &mut Vec) {
    vec.extend(self.items.iter()
        .filter(...)
        .enumerate()
        .map(...)
    );
}

```

but nothing beats **THIS** :

```rust
fn my_fn(&self, vec: &mut Vec) {
    self.items.iter()
        .filter(...)
        .enumerate()
        .map(...);
        .extend_into(vec);
}

```

`extend_into` could return the extended collection:

```rust
fn my_fn(&self, vec: &mut Vec) -> usize {
    self.items.iter()
        .filter(...)
        .enumerate()
        .map(...);
        .extend_into(vec)
        .len()
}

```

thanks to that the function could conveniently accept collections by both reference or value:

```rust
fn my_fn(&self, mut vec: Vec) -> Vec {
    self.items.iter()
        .filter(...)
        .enumerate()
        .map(...);
        .extend_into(vec)
}

```

# Implementation

No rocket science here.

```rust
pub trait Iterator {
    type Item;

    ...

    fn extend_into<B, E>(self, extended: B) -> B
    where
        B: BorrowMut<E>,
        E: Extend<Self::Item> {
        extended.borrow_mut().extend(self);
        extended
     }
}

```

The `Borrow` allows passing collections either by value or by reference, which makes it much more elastic.

---

<div class="post-metadata">

**Author:** ![KasMA1990](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/kasma1990/32/1733_2.png) [@KasMA1990](https://internals.rust-lang.org/u/KasMA1990)\
**Post date:** [January 27, 2018, 8:43pm UTC](https://internals.rust-lang.org/t/pre-rfc-iterator-extend-into/6662/2 "2018-01-27T20:43:54Z")

</div>

I like the idea! For your `my_fn` examples, I think they should pass `&mut vec` to `extend_into` though, since `my_fn` takes `vec` by reference, no? Making separate examples for passing by reference and value is probably the best way to express this 🙂

---

<div class="post-metadata">

**Author:** ![CodeSandwich](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/codesandwich/32/3479_2.png) [@CodeSandwich](https://internals.rust-lang.org/u/CodeSandwich)\
**Post date:** [January 27, 2018, 11:07pm UTC](https://internals.rust-lang.org/t/pre-rfc-iterator-extend-into/6662/3 "2018-01-27T23:07:43Z")

</div>

Thank you! I’ve added an example of passing and returning by value. I’m not sure, if I understood your comment correctly, but in the previous examples `my_fn`s take `vec: &mut Vec`, so they don’t need to pass `&mut vec` into `exten_into`, because that would make them them actually pass `&mut &mut Vec`?

---

<div class="post-metadata">

**Author:** ![fyl2xp1](https://avatars.discourse-cdn.com/v4/letter/f/a3d4f5/32.png) [@fyl2xp1](https://internals.rust-lang.org/u/fyl2xp1)\
**Post date:** [January 28, 2018, 2:22am UTC](https://internals.rust-lang.org/t/pre-rfc-iterator-extend-into/6662/4 "2018-01-28T02:22:50Z")

</div>

Bikeshedding: I’d rather call it `collect_into`.

To me the phrase `source_iterator` `collect_into` `destination_vector` sounds more intuitive than `source_iterator` `extend_into` `destination_vector`. The latter would make me believe the iterator gets extended somehow (at least at first sight).

---

<div class="post-metadata">

**Author:** ![KasMA1990](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/kasma1990/32/1733_2.png) [@KasMA1990](https://internals.rust-lang.org/u/KasMA1990)\
**Post date:** [January 28, 2018, 9:14am UTC](https://internals.rust-lang.org/t/pre-rfc-iterator-extend-into/6662/5 "2018-01-28T09:14:17Z")

</div>

Oh right; that’s my Rust newbness showing 😃

---

<div class="post-metadata">

**Author:** ![scottmcm](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/scottmcm/32/2355_2.png) [@scottmcm](https://internals.rust-lang.org/u/scottmcm)\
**Post date:** [January 29, 2018, 8:07am UTC](https://internals.rust-lang.org/t/pre-rfc-iterator-extend-into/6662/6 "2018-01-29T08:07:59Z")

</div>

I definitely like being able to pass both `Vec::with_capacity(10)` and `&mut some_vec` 👍

Some musing on the proposed details:

- Feels kinda odd that it’s `BorrowMut`, but I guess that’s because there’s a T-for-T for that, unlike `AsMut` (which only has it for `Vec<T>`? 😕 I never understand which to use between those two…)
- How does using `BorrowMut` here compare to having a blanket impl like `impl<'a, C: Extend<T>, T> Extend<T> for &'a mut C`?

---

<div class="post-metadata">

**Author:** ![cuviper](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/cuviper/32/1897_2.png) [@cuviper](https://internals.rust-lang.org/u/cuviper)\
**Post date:** [January 29, 2018, 5:16pm UTC](https://internals.rust-lang.org/t/pre-rfc-iterator-extend-into/6662/7 "2018-01-29T17:16:04Z")

</div>

> [@scottmcm](#):
>
> How does using `BorrowMut` here compare to having a blanket impl like `impl<'a, C: Extend<T>, T> Extend<T> for &'a mut C`?

Isn't it too late to consider such a thing? I thought blanket impls on references were a breaking change.

---

<div class="post-metadata">

**Author:** ![CodeSandwich](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/codesandwich/32/3479_2.png) [@CodeSandwich](https://internals.rust-lang.org/u/CodeSandwich)\
**Post date:** [January 29, 2018, 6:39pm UTC](https://internals.rust-lang.org/t/pre-rfc-iterator-extend-into/6662/8 "2018-01-29T18:39:48Z")

</div>

Why `BorrowMut` feels odd? It’s exactly the use case, which it was made for, to make refs and value act the same. Like you said, `BorrowMut` is implemented for every `T` and `&mut T`, while `AsMut` for every `&mut T` but only some `T`s.

---

<div class="post-metadata">

**Author:** ![hanna-kruppe](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/hanna-kruppe/32/6540_2.png) [@hanna-kruppe](https://internals.rust-lang.org/u/hanna-kruppe)\
**Post date:** [January 29, 2018, 6:54pm UTC](https://internals.rust-lang.org/t/pre-rfc-iterator-extend-into/6662/9 "2018-01-29T18:54:39Z")

</div>

> [@CodeSandwich](#):
>
> It’s exactly the use case, which it was made for, to make refs and value act the same.

Note that Borrow and BorrowMut take this quite far: They demand that Hash, Ord, and Eq impls must agree. That's because they are actually made for collection elements (e.g., to be able to search a map of `String` keys with a `&str` key), while AsRef/AsMut is the more general one. In that sense, it is quite strange to use BorrowMut for something that has nothing to do with Ord, Eq, or Hash.

---

<div class="post-metadata">

**Author:** ![CodeSandwich](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/codesandwich/32/3479_2.png) [@CodeSandwich](https://internals.rust-lang.org/u/CodeSandwich)\
**Post date:** [January 29, 2018, 7:08pm UTC](https://internals.rust-lang.org/t/pre-rfc-iterator-extend-into/6662/10 "2018-01-29T19:08:25Z")

</div>

Hmm, I looked up the `BorrowMut` docs and found no `Hash`, `Ord` or `Eq` constraints, so I dont’ think they will ever get in user’s way. The fact, that these methods operate on `&self`, indeed makes result of `T.borrow_mut()` impl them if `T` does, but I can’t understand how does it matter?

---

<div class="post-metadata">

**Author:** ![hanna-kruppe](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/hanna-kruppe/32/6540_2.png) [@hanna-kruppe](https://internals.rust-lang.org/u/hanna-kruppe)\
**Post date:** [January 29, 2018, 7:21pm UTC](https://internals.rust-lang.org/t/pre-rfc-iterator-extend-into/6662/11 "2018-01-29T19:21:56Z")

</div>

It's not that the traits require Ord/Eq/Hash to be implemented too, it's that they require:

> If you are implementing Borrow and both Self and Borrowed implement Hash, Eq, and/or Ord, they must produce the same result.

(Source: [Borrow in std::borrow - Rust](https://doc.rust-lang.org/std/borrow/trait.Borrow.html))

---

<div class="post-metadata">

**Author:** ![CodeSandwich](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/codesandwich/32/3479_2.png) [@CodeSandwich](https://internals.rust-lang.org/u/CodeSandwich)\
**Post date:** [January 29, 2018, 7:46pm UTC](https://internals.rust-lang.org/t/pre-rfc-iterator-extend-into/6662/12 "2018-01-29T19:46:17Z")

</div>

I see, so you’re saying, that BorrowMut might be too strict for this use case? An alternative would be to define own trait, almost the same, but without these soft constraints. But is it worth it? BorrowMut is already in standard library and widely used, so interface using it might be in practice more elastic.

---

<div class="post-metadata">

**Author:** ![withoutboats](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/withoutboats/32/4560_2.png) [@withoutboats](https://internals.rust-lang.org/u/withoutboats)\
**Post date:** [January 29, 2018, 8:18pm UTC](https://internals.rust-lang.org/t/pre-rfc-iterator-extend-into/6662/13 "2018-01-29T20:18:12Z")

</div>

`AsMut` is the correct trait for this behavior, but there is no `AsMut<T> for T` for coherence reasons.

---

<div class="post-metadata">

**Author:** ![CodeSandwich](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/codesandwich/32/3479_2.png) [@CodeSandwich](https://internals.rust-lang.org/u/CodeSandwich)\
**Post date:** [January 29, 2018, 9:03pm UTC](https://internals.rust-lang.org/t/pre-rfc-iterator-extend-into/6662/14 "2018-01-29T21:03:31Z")

</div>

I disagree. [Documentation](https://doc.rust-lang.org/std/convert/trait.AsRef.html) states that `AsRef is to be used when wishing to convert to a reference of another type. Borrow is more related to the notion of taking the reference.` This use case is about obtaining reference no matter in what form comes the collection, not about converting reference type.

---

<div class="post-metadata">

**Author:** ![scottmcm](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/scottmcm/32/2355_2.png) [@scottmcm](https://internals.rust-lang.org/u/scottmcm)\
**Post date:** [January 30, 2018, 12:36am UTC](https://internals.rust-lang.org/t/pre-rfc-iterator-extend-into/6662/15 "2018-01-30T00:36:44Z")

</div>

> [@CodeSandwich](#):
>
> Why BorrowMut feels odd?

Because other places that allow both owned or borrowed use AsRef, like [File in std::fs - Rust](https://doc.rust-lang.org/std/fs/struct.File.html#method.open)

---

<div class="post-metadata">

**Author:** ![ExpHP](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/exphp/32/6208_2.png) [@ExpHP](https://internals.rust-lang.org/u/ExpHP)\
**Post date:** [January 30, 2018, 3:00am UTC](https://internals.rust-lang.org/t/pre-rfc-iterator-extend-into/6662/16 "2018-01-30T03:00:34Z")

</div>

> [@scottmcm](#):
>
> Because other places that allow both owned or borrowed use AsRef

That is done almost exclusively for specific (and almost always unsized) targets. In my eyes, AsRef is useless for abstracting over arbitrary T and `&T`.

---

<div class="post-metadata">

**Author:** ![CodeSandwich](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/codesandwich/32/3479_2.png) [@CodeSandwich](https://internals.rust-lang.org/u/CodeSandwich)\
**Post date:** [January 30, 2018, 9:22am UTC](https://internals.rust-lang.org/t/pre-rfc-iterator-extend-into/6662/17 "2018-01-30T09:22:55Z")

</div>

The `Path` case is not about owned and not owned, it’s about **cheap conversion**. Look up, what is `AsRef<Path>`:

- `Components<'a>`
- `std::path::Iter<'a>`
- `Path` **\<== that had to explicitly implemented for ease of use**
- `OsStr`
- `Cow\<'a, OsStr\>``
- `OsString`
- `str`
- `String`
- `PathBuf`

Also notice, what’s **not** `AsRef<T>`:

- `AsRef<BTreeMap>` for `BTreeMap`
- `AsRef<BTreeSet>` for `BTreeSet`
- `AsRef<LinkedList>` for `LinkedList`
- a lot more

That’s because `AsRef is to be used when wishing to convert to a reference of another type. Borrow is more related to the notion of taking the reference.`

---

<div class="post-metadata">

**Author:** ![system](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/system/32/14092_2.png) [@system](https://internals.rust-lang.org/u/system)\
**Post date:** [March 25, 2019, 8:29am UTC](https://internals.rust-lang.org/t/pre-rfc-iterator-extend-into/6662/18 "2019-03-25T08:29:35Z")

</div>

Closed on March 25, 2019, 8:29am UTC

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.
