# Why is there no repeat for String and Vec?

**URL:** <https://internals.rust-lang.org/t/why-is-there-no-repeat-for-string-and-vec/20857>\
**Category:** libs\
**Created:** [May 18, 2024, 11:31am UTC](https://internals.rust-lang.org/t/why-is-there-no-repeat-for-string-and-vec/20857 "2024-05-18T11:31:15Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![leb-kuchen](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/leb-kuchen/32/12171_2.png) [@leb-kuchen](https://internals.rust-lang.org/u/leb-kuchen)\
**Post date:** [May 18, 2024, 11:31am UTC](https://internals.rust-lang.org/t/why-is-there-no-repeat-for-string-and-vec/20857/1 "2024-05-18T11:31:15Z")

</div>

Only str and slice have a repeat method, for owned String and Vec this means one unnecessary copy.

---

<div class="post-metadata">

**Author:** ![bjorn3](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/bjorn3/32/2736_2.png) [@bjorn3](https://internals.rust-lang.org/u/bjorn3)\
**Post date:** [May 18, 2024, 12:45pm UTC](https://internals.rust-lang.org/t/why-is-there-no-repeat-for-string-and-vec/20857/2 "2024-05-18T12:45:13Z")

</div>

Even on an owned String or Vec it would likely require a copy. If the output length exceeds the capacity of the input the String or Vec will reallocate it's internal storage, which copies all elements over.

---

<div class="post-metadata">

**Author:** ![dlight](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/dlight/32/8462_2.png) [@dlight](https://internals.rust-lang.org/u/dlight)\
**Post date:** [May 18, 2024, 9:04pm UTC](https://internals.rust-lang.org/t/why-is-there-no-repeat-for-string-and-vec/20857/3 "2024-05-18T21:04:25Z")

</div>

The reallocation is not guaranteed (depends on the capacity), and can be avoided if you allocate the vec using `Vec::with_capacity` beforehand.

---

<div class="post-metadata">

**Author:** ![ryanavella](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/ryanavella/32/13254_2.png) [@ryanavella](https://internals.rust-lang.org/u/ryanavella)\
**Post date:** [May 18, 2024, 11:47pm UTC](https://internals.rust-lang.org/t/why-is-there-no-repeat-for-string-and-vec/20857/4 "2024-05-18T23:47:37Z")

</div>

You can make your own using just `Vec::reserve` and `Vec::extend_from_within`. [Here is my attempt](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=b4b8ee70d7fa2f93314c55c3392c6b1a), though I haven't tested it very thoroughly.

Unfortunately I can't encourage rustc to optimize out the redundant `reserve` calls. I tried adding assertions such as `assert!(v.len() <= v.capacity())` or `assert!(len_new <= v.capacity())` to no avail.

---

<div class="post-metadata">

**Author:** ![leb-kuchen](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/leb-kuchen/32/12171_2.png) [@leb-kuchen](https://internals.rust-lang.org/u/leb-kuchen)\
**Post date:** [May 19, 2024, 11:34am UTC](https://internals.rust-lang.org/t/why-is-there-no-repeat-for-string-and-vec/20857/5 "2024-05-19T11:34:32Z")

</div>

> [@bjorn3](#):
>
> Even on an owned String or Vec it would likely require a copy. If the output length exceeds the capacity of the input the String or Vec will reallocate it's internal storage, which copies all elements over.

can you not subtract the len itself with wrapping?

---

<div class="post-metadata">

**Author:** ![Neutron3529](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/neutron3529/32/6976_2.png) [@Neutron3529](https://internals.rust-lang.org/u/Neutron3529)\
**Post date:** [May 19, 2024, 11:39am UTC](https://internals.rust-lang.org/t/why-is-there-no-repeat-for-string-and-vec/20857/6 "2024-05-19T11:39:44Z")

</div>

Notice that, the signature for `&[T]` is

```rust
pub fn repeat(&self, n: usize) -> Vec<T>

```

Thus this is the one you should use for `Vec<T>`

In case you want to visit vec for many times, maybe `(0..times).flat_map(|_|vec.iter()).// do your stuff` is better for you.

---

<div class="post-metadata">

**Author:** ![leb-kuchen](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/leb-kuchen/32/12171_2.png) [@leb-kuchen](https://internals.rust-lang.org/u/leb-kuchen)\
**Post date:** [May 19, 2024, 12:43pm UTC](https://internals.rust-lang.org/t/why-is-there-no-repeat-for-string-and-vec/20857/7 "2024-05-19T12:43:58Z")

</div>

You can use it, but you may throw away unused allocations.

Is this not a cycle().take(n\*len) or iter::repeat().take(n).flatten()?

---

<div class="post-metadata">

**Author:** ![leb-kuchen](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/leb-kuchen/32/12171_2.png) [@leb-kuchen](https://internals.rust-lang.org/u/leb-kuchen)\
**Post date:** [May 19, 2024, 1:01pm UTC](https://internals.rust-lang.org/t/why-is-there-no-repeat-for-string-and-vec/20857/8 "2024-05-19T13:01:08Z")

</div>

Is it more about repeating a Vec a small number of times efficiently, like 10 times.

---

<div class="post-metadata">

**Author:** ![Neutron3529](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/neutron3529/32/6976_2.png) [@Neutron3529](https://internals.rust-lang.org/u/Neutron3529)\
**Post date:** [May 20, 2024, 10:43am UTC](https://internals.rust-lang.org/t/why-is-there-no-repeat-for-string-and-vec/20857/9 "2024-05-20T10:43:49Z")

</div>

> [@leb-kuchen](#):
>
> Is this not a cycle().take(n\*len) or iter::repeat().take(n).flatten()?

Actually that yields the same results as `(0..times).flat_map(|_|vec.iter())`

In case you want a real vector, the allocation is not avoidable. And in case you just want to create a read-only iterator over the repeated vector, `(0..times).flat_map(|_|vec.iter())` is enough.

---

<div class="post-metadata">

**Author:** ![kornel](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/kornel/32/2711_2.png) [@kornel](https://internals.rust-lang.org/u/kornel)\
**Post date:** [May 20, 2024, 12:24pm UTC](https://internals.rust-lang.org/t/why-is-there-no-repeat-for-string-and-vec/20857/10 "2024-05-20T12:24:30Z")

</div>

In some cases `try_reserve()` can optimize better. It has some extra hints for the optimizer, and without panic branch may be easier to optimize. But in this case I suspect LLVM just can't prove the reserved length matches later uses.

---

<div class="post-metadata">

**Author:** ![ryanavella](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/ryanavella/32/13254_2.png) [@ryanavella](https://internals.rust-lang.org/u/ryanavella)\
**Post date:** [May 20, 2024, 4:29pm UTC](https://internals.rust-lang.org/t/why-is-there-no-repeat-for-string-and-vec/20857/11 "2024-05-20T16:29:09Z")

</div>

Yes, I suspect part of the issue is that `Vec::extend_from_within` unconditionally calls `Vec::reserve`, so we can't eliminate every `reserve` call unfortunately.

I am also noticing that rustc struggles to reason that even basic `Vec` invariants such as `v.capacity() >= v.len()` are preserved across `[try_]reserve[_exact]` calls ([godbolt example](https://godbolt.org/z/br9Y51azG))

---

<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:** [August 23, 2024, 10:31pm UTC](https://internals.rust-lang.org/t/why-is-there-no-repeat-for-string-and-vec/20857/13 "2024-08-23T22:31:12Z")

</div>

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