Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add remove_item to Vecs #38143

Closed
wants to merge 0 commits into from
Closed

Conversation

madseagames
Copy link
Contributor

@madseagames madseagames commented Dec 3, 2016

Alright, so if I'm doing anything wrong please let me know. This is my first time contributing to an open source project, and I am very excited by this opportunity.

I would like to propose an addition to the standard libs. I would like to add the method remove_item to vecs. Why?

Simplicity - removing an item from a vec is overly complicated. Consider the following code:

//remove something from a vec.
fn main() {
    //create a vec
    let mut vec = vec![1, 2, 3];
    
    //we want to remove 1 from the vec, but how?
    
    //Step 1: find the position of 1 in the vec
    let pos = vec.iter().position(|x| *x == 1);
    
    //Step 2: Unwrap the position
    let pos_unwrapped = match pos {
        Some(x) => x,
        None => panic!("Coundn't find 1 in vec.")
    };
    
    //Step 3: remove the item.
    vec.remove(pos_unwrapped);
}

A new user of rust needs to know about closures, unwrapping values, iterators and two methods on vecs to simply remove an item. When I was new to rust this caused me many problems.

@rust-highfive
Copy link
Collaborator

Thanks for the pull request, and welcome! The Rust team is excited to review your changes, and you should hear from @sfackler (or someone else) soon.

If any changes to this PR are deemed necessary, please add them as extra commits. This ensures that the reviewer can see what has changed since they last reviewed the code. Due to the way GitHub handles out-of-date commits, this should also make it reasonably obvious what issues have or haven't been addressed. Large or tricky changes may require several passes of review and changes.

Please see the contribution instructions for more information.

@@ -1296,6 +1296,17 @@ impl<T: PartialEq> Vec<T> {
pub fn dedup(&mut self) {
self.dedup_by(|a, b| a == b)
}

#[stable(feature = "rust1", since = "1.0.0")]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi! This would be introduced as an unstable feature if introduced. This should be an unstable tag, and you specify a new feature name that you invent for feature=. See dedup_by_key in the same file for an example.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, will do. I wasn't entirely sure what to put for feature :P

None => return None,
};

self.remove(pos);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps return type should be Option<(usize, T)>, returning Some((pos, self.remove(pos)))

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why would you return both pos and self.remove(pos)? Would they not be the same thing, an index to the item to be removed?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

self.remove(pos) returns the element

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahh, ok. I was under the impression that remove returned the index to the item removed. Option<(usize, T)> seems like a good idea to me.

@@ -1296,6 +1296,17 @@ impl<T: PartialEq> Vec<T> {
pub fn dedup(&mut self) {
self.dedup_by(|a, b| a == b)
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line has trailing whitespace which will need to be removed, that's why travis failed

@steveklabnik
Copy link
Member

/cc @rust-lang/libs

@@ -1296,6 +1296,17 @@ impl<T: PartialEq> Vec<T> {
pub fn dedup(&mut self) {
self.dedup_by(|a, b| a == b)
}

#[unstable(feature = "remove_from", reason = "recently added", issue = "38143")]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this feature be called "remove_item"?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or maybe even "vec_remove_item"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should be, I'll call it vec_remove_item

@madseagames madseagames changed the title Add remove_from to Vecs Add remove_item to Vecs Dec 4, 2016
@sfackler
Copy link
Member

sfackler commented Dec 4, 2016

In what context would a user want to know the index from which the value was removed? Similar methods in Java and Python do not return the index AFAIKT.

@madseagames
Copy link
Contributor Author

@sfackler I've been trying to come up with a use case and I've found none. Perhaps Option(T) would be the best way to go?

@sfackler
Copy link
Member

sfackler commented Dec 7, 2016

That's what I would vote for, yeah. It might also be helpful to make the item argument generic over Borrow<T>, which is what we've done for things like binary_search: #37761

@aturon
Copy link
Member

aturon commented Dec 8, 2016

I'm tentatively in favor of this API, with a couple of changes:

  • Renaming to simply remove, to bring into alignment with other collections (e.g. HashMap)
  • Changing the return type to Option<T> as previously suggested.

@sfackler
Copy link
Member

sfackler commented Dec 8, 2016

remove already exists for removal by index I believe.

@aturon
Copy link
Member

aturon commented Dec 9, 2016

@sfackler Oh whoops, of course. In that case, remove_item is a pretty reasonable name.

@madseagames
Copy link
Contributor Author

madseagames commented Dec 9, 2016

Changed return value to Option<T> T being the item returned by remove(pos).

@steveklabnik
Copy link
Member

I've restarted Travis as it's not clear to me that the failure was legit.

@sfackler
Copy link
Member

@rfcbot fcp merge

@alexcrichton alexcrichton added the T-libs-api Relevant to the library API team, which will review and decide on the PR/issue. label Jan 19, 2017
@alexcrichton
Copy link
Member

@rfcbot fcp merge

@rfcbot
Copy link

rfcbot commented Jan 19, 2017

Team member @alexcrichton has proposed to merge this. The next step is review by the rest of the tagged teams:

No concerns currently listed.

Once these reviewers reach consensus, this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up!

See this document for info about what commands tagged team members can give me.

@brson
Copy link
Contributor

brson commented Jan 20, 2017

It seems almost certain if we add a function to remove a value by comparison to another concrete value, that we will eventually also be asked to add remove_by, taking a closure. Then we will be asked to add HashMap::remove_by. Does that sound ok?

@alexcrichton
Copy link
Member

@brson seems reasonable to me, yes.

@cristicbz
Copy link
Contributor

My only concern here is to do with remove vs swap_remove. The only times I've ever wanted to do this with a Vec has been with swap_remove (when I want to preserve ordering, it generally ends up involving something more general, better served by retain). Will we find ourselves adding swap_remove_item and swap_remove_by?

@aturon
Copy link
Member

aturon commented Jan 23, 2017

@cristicbz That's possible, though we should keep in mind that these are all conveniences (and so we don't have to offer every possible combination). That said, in my experience there's relatively little cost in adding something that follows a well-known convention, because you immediately know what it does from the name.

@@ -1296,6 +1296,16 @@ impl<T: PartialEq> Vec<T> {
pub fn dedup(&mut self) {
self.dedup_by(|a, b| a == b)
}

#[unstable(feature = "vec_remove_item", reason = "recently added", issue = "38143")]
Copy link
Contributor

@clarfonthey clarfonthey Jan 29, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should have a doc comment clarifying that it removes the first item found.

@clarfonthey
Copy link
Contributor

clarfonthey commented Jan 29, 2017

  1. I think that it'd be best to also implement this method for VecDeque for consistency.
  2. Should there be a remove_last_item which uses rposition instead?
  3. I'm personally a fan of find_remove, but we can still go with remove_item.

@aturon
Copy link
Member

aturon commented Jan 31, 2017

@clarcharr

  1. I think that it'd be best to also implement this method for VecDeque for consistency.

Agreed.

  1. Should there be a remove_last_item which uses rposition instead?

Unclear to me. This is one problem with convenience methods: it's not clear where to draw the line. I'm not opposed, though.

  1. I'm personally a fan of find_remove, but we can still go with remove_item.

I think remove_item is better because the primary action here is removing -- and you're likely to be browsing for remove rather than find if you're looking for this API.

@aturon
Copy link
Member

aturon commented Jan 31, 2017

Ping @brson

@alexcrichton
Copy link
Member

@madseagames in preparation for merging, could you be sure to document this method as well?

We also tend to not require full consensus before merging new unstable APIs, so if you want to ping me when updated I'll r+!

@alexcrichton
Copy link
Member

@madseagames oh also can you file a tracking issue and update the reference? If you cc me on the issue I'll be sure to tag it appropriately

@bors
Copy link
Contributor

bors commented Feb 24, 2017

💔 Test failed - status-appveyor

@alexcrichton
Copy link
Member

alexcrichton commented Feb 24, 2017 via email

@bors
Copy link
Contributor

bors commented Feb 24, 2017

⌛ Testing commit e86846d with merge 0bea301...

@bors
Copy link
Contributor

bors commented Feb 24, 2017

💔 Test failed - status-travis

@alexcrichton
Copy link
Member

@bors: retry

  • network error

@eddyb
Copy link
Member

eddyb commented Feb 25, 2017

@bors r- Doc test needs feature-gate too.

@madseagames
Copy link
Contributor Author

@alexcrichton Whats going on with Travis? Anything I need to change? Also, when will we be seeing remove_item in the rust std libs? Will it be part of the nightly or beta?

@eddyb
Copy link
Member

eddyb commented Mar 5, 2017

@madseagames The example in the documentation needs the feature gate too.

@alexcrichton
Copy link
Member

@madseagames oh the example here needs the same feature name as the method itself (as evidenced by the Travis error)

@alexcrichton
Copy link
Member

Thanks @madseagames! Could you also squash the commits down into one as well?

@@ -1165,6 +1165,15 @@ impl<T> Vec<T> {
}
other
}

pub fn remove_item<T: PartialEq>(&mut self, item: T) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm sorry, I'm having some issues with github at the moment, Im working on it, I'm an absolute newbie to github and I'm trying to fix things

Copy link
Member

@eddyb eddyb Mar 7, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I recommend trying out git gui, especially in amend mode, and then force-pushing.

@eddyb
Copy link
Member

eddyb commented Mar 7, 2017

@madseagames You should still squash (git rebase -i c80c31a502c838f9ec06f1003d7c61cf9de9d551 then follow the instructions - you can use something like upstream/master instead of that commit hash but I'm not sure if your https://github.com/rust-lang/rust remote is called upstream).
Also, I think you still have two copies of the definition (again, git gui makes it super easy to fix that).

@madseagames
Copy link
Contributor Author

@eddyb So far I've been doing everything through the github website, is there a way to squash through the site? Or do I need to download the command line tool?

@eddyb
Copy link
Member

eddyb commented Mar 7, 2017

@madseagames Ohhhh that explains things. Well, I'm surprised you got this far, the web UI is unusable for anything more than tiny changes and a single commit. I think I can fix it for you though.

@madseagames
Copy link
Contributor Author

madseagames commented Mar 7, 2017

@eddyb How would you go about doing that? Now that you mention it I do have two definitions...

@clarfonthey
Copy link
Contributor

@madseagames if you use Windows or OS X, you should be able to download GitHub's git UI that should let you squash pull requests.

@eddyb
Copy link
Member

eddyb commented Mar 7, 2017

Uhm, this is very surprising.

@eddyb
Copy link
Member

eddyb commented Mar 7, 2017

@madseagames I tried to use a new GitHub feature but it emptied&closed the pull request instead.

EDIT: Aaaaand let it be known I suck at git, I used the wrong source branch, see #40325.

@madseagames
Copy link
Contributor Author

Haha, glad to know I'm not the only one that sucks at git :P also @clarcharr I run Linux. I tried to learn git once but figured that taking so much time to learn such a complex tool wasn't worth it.

@eddyb
Copy link
Member

eddyb commented Mar 7, 2017

@madseagames Oh, all of this could've been avoided, when you said "download the command-line tool" I thought you were on Windows where it's actually some work 😆 (if you want to learn, again, git gui is your friend - had I used it to push here I wouldn't have pushed the wrong thing to your branch).

@madseagames
Copy link
Contributor Author

@eddyb so... Are things fixed? I'm still not entirely sure. I removed the second definition, did you squash the commits?

@eddyb
Copy link
Member

eddyb commented Mar 7, 2017

@madseagames This PR is broken permanently AFAICT, had to open #40325 (which has 1 commit).

@madseagames
Copy link
Contributor Author

@eddyb what do I need to do at my end?

@eddyb
Copy link
Member

eddyb commented Mar 7, 2017

@madseagames Hopefully nothing, if #40325 merges.

frewsxcv added a commit to frewsxcv/rust that referenced this pull request Mar 8, 2017
Added remove_from to vec.rs (rust-lang#38143)

Turns out that if you push to someone's PR branch and cause the PR to close, you lose delegation 😞.

@madseagames I'm really sorry about that 😭
frewsxcv added a commit to frewsxcv/rust that referenced this pull request Mar 8, 2017
Added remove_from to vec.rs (rust-lang#38143)

Turns out that if you push to someone's PR branch and cause the PR to close, you lose delegation 😞.

@madseagames I'm really sorry about that 😭
arielb1 pushed a commit to arielb1/rust that referenced this pull request Mar 8, 2017
Added remove_from to vec.rs (rust-lang#38143)

Turns out that if you push to someone's PR branch and cause the PR to close, you lose delegation 😞.

@madseagames I'm really sorry about that 😭
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
final-comment-period In the final comment period and will be merged soon unless new substantive objections are raised. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.