-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
RFC: Add Option::replace
to the core library
#2296
Conversation
Option::replace
to the core library
Conversation started on the Extra methods for |
a8ecfce
to
00b0cc9
Compare
I do like the "replace" name more than the "give" one. |
There are two potential interpretations of this method, and I think both are useful operations. One is the one proposed here: given an The other is this: given an |
So in this case we can change the name of this method by |
I understand the second potential interpretation but it can be a strange function signature if we return an What do you think ? |
@Kerollmops No, I think |
Why not
? Then Btw, I don't find it very useful, but if we want this in stdlib then I think it should be as generic as possible. |
If we add your kind of The actual |
@joshtriplett Wouldn't the second kind of replace be a |
That’d be called |
There’re a lot of ways to go with that: let x = Some(3);
let y = x.map(|a| a * 10); or, if you want mutable: let mut x = Some(3);
if let Some(ref mut a) = x {
*a = *a * 10;
} You can add such as a method, but I’m not sure it’s that useful, as it’d somehow encourage people to have more Also, please replace that paragraph about |
The problem with the first is that you don't change the value in-place, you change that: let mut x = Some(3);
x = x.map(|a| a * 10); But in this case you don't retrieve the old value. The second solution has the same disavantage, you can't retrieve the old value or by changing the code. And You don't think it's more convenient to write this ? let mut x = Some(3);
let y = x.replace(30); |
Ok I got what you want. fn replace<A>(a: &mut Option<A>, v: A) -> Option<A> {
let old = a.take();
*a = Some(v);
old
} |
In the rendered file I provide a simple implementation like that: fn replace<T>(&mut self, value: T) -> Option<T> {
mem::replace(self, Some(value))
} More easy to understand and mimic in some way the current |
Actually, it’d make a good candidate since most containers have a |
Thanks I will add that to the RFC. It's true, many containers have these |
82657ab
to
fa88efb
Compare
Ping! What do I need to do to make it be real ? |
Triage ping random person in @rust-lang/libs. |
I will try to ping @SimonSapin, so 👍 |
Please edit your
impl<T> Option<T> {
fn map_in_place(&mut self, x: T) { // or map_mut, or whatever name suits you
if let Some(ref mut inner) = *self {
*inner = x;
}
}
} |
I went ahead and fixed this :) |
Also, something you should address in the RFC drawback / unresolved section: you might introduce a breaking change. Imagine the following code: trait Replace {
type Item;
fn replace(&mut self, x: Self::Item) -> Self;
}
impl<T> Replace for Option<T> {
type Item = T;
fn replace(&mut self, x: Self::Item) -> Self {
mem::replace(self, Some(x))
}
} Introducing your |
Team member @SimonSapin has proposed to merge this. The next step is review by the rest of the tagged teams: No concerns currently listed. Once a majority of reviewers approve (and none object), 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. |
@Centril doesn't the FCP last 10 days ? 😄 |
@Kerollmops It does, but only starts after enough team member reviews. Ping @alexcrichton, @sfackler, @withoutboats |
@Kerollmops this is only in PFCP atm and requires team members to ✅ their boxes. |
@SimonSapin damn you are fast :) |
🔔 This is now entering its final comment period, as per the review above. 🔔 |
How would
be better than
It seems to me that this function is not worth putting in the standard library. |
As the RFC explains it, the |
UPDATE: There is a separate RFC #2490 for this now. I wonder if somebody has already discussed something like #[inline]
fn replace_with<F>(&mut self, f: F) where F: FnOnce(Option<T>) -> Option<T> {
let mut x = f(self.take());
mem::swap(self, &mut x);
debug_assert!(x.is_none());
mem::forget(x);
} The use-case is somewhat similar to let mut merged = merge(lower_node.right.take(), Some(greater_node));
mem::swap(&mut lower_node.right, &mut merged);
mem::forget(merged);
Some(lower_node) NOTE: If I replace the Here is what I would love to write instead: lower_node.right.replace_with(|node| merge(node, Some(greater_node)));
Some(lower_node) @thomas-huet The two blocks of code you provide are not equivalent. The equivalent of the first block would be: let mut x = Some(2);
let old = x.take();
x = Some(5); Well, this is still not a complete equivalent as it would make unnecessary |
This is another discussion and it has already been talked in this thread. Why not opening an RFC ? The real equivalent of the let old = mem::replace(&mut self, Some(value)); |
I am new to this process and this issue was the closest that I could have found on the tracker, so I decided to ask here first. I will try to prepare a separate RFC. |
@frol I understand that the first block creates the variable Actually my main problem with this RFC is its motivation: option can be seen as a container (I guess it depends on your definition of container but I would think that a container is not limited to a size of one) and some other containers have a |
I second what @thomas-huet said: no strong arguments to include |
I add faced some cases where this method could have been useful. And I think this is a method that must be present to help newcomers use the standard library. It feels to me like a lack to not have this method, because we have a similar one named struct Kitchen {
chef: Option<Chef>,
}
impl Kitchen {
fn remove_the_chef(&mut self) -> Option<Chef> {
self.chef.take()
}
fn replace_the_chef(&mut self, new: Chef) -> Option<Chef> {
self.chef.replace(new)
}
} |
@raindev Well, here you go some examples from Rust compiler internals: |
@Kerollmops, @frol, thanks for the examples. Naively repping Rust's codebase (which is a massive project) there are 3 places where
|
The final comment period, with a disposition to merge, as per the review above, is now complete. |
@SimonSapin there has been some recent discussion on the usefulness of the operation... Is your position unchanged that it should be merged? If so, I'll run the RFC merge procedure. |
FYI, I have just created RFC #2490 for |
Huzzah! This RFC has been merged! Tracking issue: rust-lang/rust#51998 |
Add the method
Option::replace
to the core library. This method makes possible to easily replace the value of an option to some value (Some(value)
).Rendered
Tracking issue