-
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
take on bool
#3189
take on bool
#3189
Conversation
Prior art: Probably it doesn't make sense to name this operation |
let val = *self; | ||
// and reset ourselves to false. If we are already false, | ||
// then this doesn't matter. | ||
*self = false; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should perhaps note that using core::mem::take
does not actually optimize quite as well. It has an extra instruction compared:
mov al, byte ptr [rdi]
+ and al, 1
mov byte ptr [rdi], 0
ret
(Godbolt)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yup -- I didn't want to get too in the weed here, but that's a great point. It mostly goes away once you call the method though
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's not a reason to add this method, though, because it's a problem with every single two-variant enum, not just bool
: https://rust.godbolt.org/z/1Wjs1bf3Y.
Its root cause is LLVM discarding information about the possible values of the discriminant. rust-lang/rust#85133 (comment) This "just" needs to get fixed, since it's actually hurting substantial amounts of Option
- and Result
-using code too.
text/3189-take-on-bool.md
Outdated
|
||
# Guide-level explanation | ||
|
||
All `.take` does is return the value of a boolean while also setting that value internally to `false`. It is exactly similar to `Option::take`, except that, of course, it only returns `true/false` instead of some inner value. (In this sense, this `.take` is effectively the same as `Option::take().is_some()`). In any example where flags are commonly read while also being reset, this method is useful. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The comparison to Option::take
is a little confusing. A more direct comparison would be to mem::take
:
Something like:
All
.take()
does is return the value of a boolean while also setting that value internally tofalse
. It is just likemem::take
, except it is called as a method instead of a free function. In places where booleans are commonly read and then reset, like dirty flags, this method is useful.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a great point. I'll make this edit.
Micro-optimization aside, is there a reason to want this rather than mem::take? A similar method could appear on any type that implements Default, but I don't think we should add such a method to every such type. |
|
Hmm, actually, maybe this could be a provided method on |
Given that |
If adding it to Default is too hard, it could be done via an extension trait |
Yes, for two reasons:
As a general statement here though, I suspect this PR divides users cleanly into "I have always wanted this and wished it existed" and "I have never wanted that, and I think it's bloat." |
Also updated with feedback from @kpreid and @mbartlett21, thank you both! |
Adding |
Perhaps you could put this under the Motivation section, saying why |
thank you! |
adding a |
To me a Depending on the scale of the problem, in my code I'd use one of:
and I'd prefer any of these to |
➕💯 to @tanriol's post here. I agree that most That said, my opposition here is basically entirely to the precedent from naming this If this was instead phrased as impl bool {
#[must_use = "If you don't need the return value, just use `= false`"]
pub reset(&mut self) -> bool {
mem::replace(self, false)
}
#[must_use = "If you don't need the return value, just use `= true`"]
pub set(&mut self) -> bool {
mem::replace(self, true)
}
} |
/* | ||
// without this RFC, our code would be slightly uglier like this: | ||
if self.dirty { | ||
self.dirty = false; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As a reader, I prefer this version. It is only one line longer and it is much clearer what is going on. take
is not immediately obvious unless you are very familiar with the option version, and even then I think you might stop for a minute to consider the semantics (looking just at self.dirty.take()
I might assume dirty
is being treated as some kind of pointer and left as null
).
(I also have a preference against functions which have both an important side effect and return an important value, they tend to be 'too clever' and to surprise readers).
@rfcbot close |
Team member @joshtriplett has proposed to close this. The next step is review by the rest of the tagged team members: No concerns currently listed. Once a majority of reviewers approve (and at most 2 approvals are outstanding), 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. |
🔔 This is now entering its final comment period, as per the review above. 🔔 |
The final comment period, with a disposition to close, as per the review above, is now complete. As the automated representative of the governance process, I would like to thank the author for their work and everyone else who contributed. This is now closed. |
This RFC proposes adding a method called
take
onbool
, which will return the value of the bool while also settingbool
tofalse
, similar toOption::take
.Rendered