# Should \`Vec\` have a \`try\_remove(&mut self, usize) -\> Option\<T\>\` function

**URL:** <https://internals.rust-lang.org/t/should-vec-have-a-try-remove-mut-self-usize-option-t-function/15964>\
**Category:** libs\
**Created:** [January 15, 2022, 2:22pm UTC](https://internals.rust-lang.org/t/should-vec-have-a-try-remove-mut-self-usize-option-t-function/15964 "2022-01-15T14:22:57Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![cameron1024](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/cameron1024/32/8959_2.png) [@cameron1024](https://internals.rust-lang.org/u/cameron1024)\
**Post date:** [January 15, 2022, 2:22pm UTC](https://internals.rust-lang.org/t/should-vec-have-a-try-remove-mut-self-usize-option-t-function/15964/1 "2022-01-15T14:22:57Z")

</div>

This seems like a common enough request that it has probably been discussed elsewhere, but the closest I could find was this [Reddit thread](https://www.reddit.com/r/rust/comments/6e151u/why_doesnt_vecremove_return_an_option/%5D) regarding changing `Vec::remove` to return an `Option`, which is obviously a very breaking change.

My suggestion is a new function with the rough implementation:

```rust
impl<T> Vec<T> {
  fn try_remove(&mut self, index: usize) -> Option<T> {
    if self.len() < index {
      Some(self.remove(index))
    } else {
      None
    }
  }
}

```

I imagine a similar function could be added for `try_swap_remove`.

Do people think this API would be useful? Is it "too similar to `.remove()`"? Personally I found it odd that such a function doesn't exist, but is that frustration shared with other people? Is there some reason I'm not seeing that makes such an API problematic?

I was planning to put up a PR, and get feedback there, but thought best to create a Github issue first, which brought me here.

---

<div class="post-metadata">

**Author:** ![steffahn](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/steffahn/32/13288_2.png) [@steffahn](https://internals.rust-lang.org/u/steffahn)\
**Post date:** [January 15, 2022, 4:56pm UTC](https://internals.rust-lang.org/t/should-vec-have-a-try-remove-mut-self-usize-option-t-function/15964/2 "2022-01-15T16:56:22Z")

</div>

> [@cameron1024](#):
>
> ```rust
> if self.len() < index {
> Some(self.remove(index))
> } else {
> None
> }
> 
> ```

I suppose you mean `if self.len() > index`.

Note that you can shorten this to

```rust
(index < self.len()).then(|| self.remove(index))

```

if you want to have `try_remove`-like functionality in your code right now.

---

<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:** [January 15, 2022, 5:18pm UTC](https://internals.rust-lang.org/t/should-vec-have-a-try-remove-mut-self-usize-option-t-function/15964/3 "2022-01-15T17:18:30Z")

</div>

Does libstd have any `try_` methods yet that return `Option`? I think there would be a question whether try\_ should be reserved only for `Result` methods (e.g. `Result<T, VecIndexOutOfBoundsError>`)

---

<div class="post-metadata">

**Author:** ![steffahn](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/steffahn/32/13288_2.png) [@steffahn](https://internals.rust-lang.org/u/steffahn)\
**Post date:** [January 15, 2022, 5:38pm UTC](https://internals.rust-lang.org/t/should-vec-have-a-try-remove-mut-self-usize-option-t-function/15964/4 "2022-01-15T17:38:28Z")

</div>

> [@kornel](#):
>
> Does libstd have any `try_` methods yet that return `Option` ?

AFAICT, no.

```plaintext
 ~/forks/rust/library > master > rg -U "pub fn try.*\(([^{]|\n)*?\) -> Option"
std/src/sys/sgx/waitqueue/spin_mutex.rs
48: pub fn try_lock(&self) -> Option<SpinMutexGuard<'_, T>> {

std/src/sys_common/remutex.rs
101: pub fn try_lock(self: Pin<&Self>) -> Option<ReentrantMutexGuard<'_, T>> {

core/src/num/dec2flt/number.rs
52: pub fn try_fast_path<F: RawFloat>(&self) -> Option<F> {

```

those all seem to be public-in-private.

---

<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 15, 2022, 7:16pm UTC](https://internals.rust-lang.org/t/should-vec-have-a-try-remove-mut-self-usize-option-t-function/15964/5 "2022-01-15T19:16:49Z")

</div>

> [@cameron1024](#):
>
> I imagine a similar function could be added for `try_swap_remove` .

It could be done for every single thing that takes an index.

It's not obvious to me that adding all those things is useful, though. Especially for `remove`, you have to have come up with the index _from_ somewhere. So how often does it really come up that you're trying to remove something where you don't know that it's in-range already?

It's easy to check the index is in-range yourself, in a place where it really doesn't already know, so adding more methods for it doesn't seem worth it to me.

---

<div class="post-metadata">

**Author:** ![cameron1024](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/cameron1024/32/8959_2.png) [@cameron1024](https://internals.rust-lang.org/u/cameron1024)\
**Post date:** [January 15, 2022, 9:20pm UTC](https://internals.rust-lang.org/t/should-vec-have-a-try-remove-mut-self-usize-option-t-function/15964/6 "2022-01-15T21:20:10Z")

</div>

> So how often does it really come up that you're trying to remove something where you don't know that it's in-range already?

Ah I see what you mean. The case that motivated this for me was "popping" items from the front of the stack, so my example use case would be `vec.try_remove(0)`. Admittedly, that's probably the only way to call it without immediately `unwrap`ping the `Option` you get back.

Maybe what I'm after instead would be something more like `remove_first(&mut self) -> Option<T>`? That also avoids the question of "can an `Option`-returning function be called `try_foo`"

---

<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 15, 2022, 9:27pm UTC](https://internals.rust-lang.org/t/should-vec-have-a-try-remove-mut-self-usize-option-t-function/15964/7 "2022-01-15T21:27:00Z")

</div>

> [@cameron1024](#):
>
> Maybe what I'm after instead would be something more like `remove_first(&mut self) -> Option<T>` ?

At that point, though, wouldn't you want [https://doc.rust-lang.org/std/collections/struct.VecDeque.html#method.pop\_front](https://doc.rust-lang.org/std/collections/struct.VecDeque.html#method.pop_front) instead? Not having a perfect method for something discouraged is often a good thing.

(And for `0` specifically, `if !v.is_empty() { v.remove(0); }` doesn't seem so bad.)

---

<div class="post-metadata">

**Author:** ![steffahn](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/steffahn/32/13288_2.png) [@steffahn](https://internals.rust-lang.org/u/steffahn)\
**Post date:** [January 15, 2022, 9:28pm UTC](https://internals.rust-lang.org/t/should-vec-have-a-try-remove-mut-self-usize-option-t-function/15964/8 "2022-01-15T21:28:12Z")

</div>

If you need to regularly remove the first item of a `Vec`, you might be using the wrong data structure, since every remove is an O(n) operation.

Unless you use swap\_remove, but in that case, the order of the `Vec` is quickly messed up, and if order doesn't matter you might as well `pop` the last element to begin with.

To efficiently use remove and push in an alternating manner, use `VecDeque`; to remove a bunch of first items in a row, turning it into an iterator might make sense.

---

<div class="post-metadata">

**Author:** ![cameron1024](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/cameron1024/32/8959_2.png) [@cameron1024](https://internals.rust-lang.org/u/cameron1024)\
**Post date:** [January 16, 2022, 1:40pm UTC](https://internals.rust-lang.org/t/should-vec-have-a-try-remove-mut-self-usize-option-t-function/15964/9 "2022-01-16T13:40:26Z")

</div>

Yeah, sounds like I'm probably using the wrong data structure. Thanks for the insight 🙂

---

<div class="post-metadata">

**Author:** ![elidupree](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/elidupree/32/4304_2.png) [@elidupree](https://internals.rust-lang.org/u/elidupree)\
**Post date:** [January 16, 2022, 3:07pm UTC](https://internals.rust-lang.org/t/should-vec-have-a-try-remove-mut-self-usize-option-t-function/15964/10 "2022-01-16T15:07:54Z")

</div>

It's interesting to realize how I've never had a need for this method, despite frequently using `get` for its Option-ness.

I think the reason here is: the most common situation where you want any method that takes an index, is the situation where there are _stable indices_ – e.g. you construct an array once, and then use array indices as positions you're moving around between, without adding or removing any elements from the array in the meantime. The moment you call `remove`, any indices after the removed element lose their meaning.

---

<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:** [April 16, 2022, 3:08pm UTC](https://internals.rust-lang.org/t/should-vec-have-a-try-remove-mut-self-usize-option-t-function/15964/11 "2022-04-16T15:08:13Z")

</div>

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