-
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
Add methods for converting from bool
to Option<T>
#2757
Closed
Closed
Changes from all commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
74d9976
Initial proposal for `bool_to_option`
varkor e271d7c
Clarify some segments
varkor 6676633
Mention `#[lang = "bool"]`
varkor 93a2c22
Add mention of reference implementation
varkor f07f27e
Rename `then` to `to_option`
varkor 2928132
Change method names to `then_some` and `then`
varkor File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
- Feature Name: `bool_to_option` | ||
- Start Date: 2019-09-05 | ||
- RFC PR: [rust-lang/rfcs#0000](https://github.com/rust-lang/rfcs/pull/0000) | ||
- Rust Issue: [rust-lang/rust#0000](https://github.com/rust-lang/rust/issues/0000) | ||
|
||
# Summary | ||
[summary]: #summary | ||
|
||
Add methods to `bool` for converting to an `Option<T>`, given a `t: T`, where `true` maps | ||
to `Some(t)` and `false` maps to `None`, abstracting the following common pattern in Rust. | ||
|
||
```rust | ||
if some_condition { | ||
Some(t) | ||
} else { | ||
None | ||
} | ||
``` | ||
|
||
# Motivation | ||
[motivation]: #motivation | ||
|
||
This is an | ||
[extremely common pattern](https://sourcegraph.com/search?q=repogroup%3Acrates+%2Felse%5Cs*%7B%5Cs*None%5Cs*%7D%2F+count%3A1000) | ||
in Rust code, but is quite verbose, taking several lines to achieve something with only two | ||
important data: the `bool` and the `T`. If we instead collapse the expression on to a single line by | ||
simply removing newlines (i.e. `if some_condition { Some(t) } else { None }`), the legibility of the | ||
code is reduced. In addition, chaining a conversion from a `bool` to an `Option<T>` is inconvenient | ||
in this form and usually requires binding an extra variable to remain readable. Abstracting this | ||
common pattern into a method will make code more readable and require less repetitive typing on the | ||
user's part. | ||
|
||
A method for converting from `bool` to `Option<T>` has been requested several times in the past | ||
[[1]](https://github.com/rust-lang/rfcs/pull/2180) | ||
[[2]](https://github.com/rust-lang/rust/issues/50523) | ||
[[3]](https://github.com/rust-lang/rfcs/issues/2606) and shows a significant desire from users. | ||
|
||
# Reference-level explanation | ||
[reference-level-explanation]: #reference-level-explanation | ||
|
||
Following this proposal, we will add two methods to `bool`: | ||
|
||
```rust | ||
impl bool { | ||
fn then_some<T>(self, t: T) -> Option<T> { | ||
if self { | ||
Some(t) | ||
} else { | ||
None | ||
} | ||
} | ||
|
||
fn then<T, F: FnOnce() -> T>(self, f: F) -> Option<T> { | ||
if self { | ||
Some(f()) | ||
} else { | ||
None | ||
} | ||
} | ||
} | ||
``` | ||
|
||
The primitive type `bool` currently has no methods, so it will be necessary to add support similarly | ||
to other primitive types that do have methods, like | ||
[`char`](https://doc.rust-lang.org/src/core/char/methods.rs.html#11-1393). This will require the | ||
addition of a new lang item: `#[lang = "bool"]`. | ||
|
||
A reference implementation is provided in [#64255](https://github.com/rust-lang/rust/pull/64255). | ||
|
||
# Drawbacks | ||
[drawbacks]: #drawbacks | ||
|
||
Save the usual drawbacks of adding a new method to the standard library, there are no | ||
drawbacks. | ||
|
||
# Rationale and alternatives | ||
[rationale-and-alternatives]: #rationale-and-alternatives | ||
|
||
The implementations here are the only reasonable ones. | ||
|
||
The following names have been suggested in the past. The choice in this proposal has been made to | ||
avoid possible confusion (e.g. avoiding a name that suggests a conversion from `bool` to | ||
`Option<()>` rather than `Option<T>`), and to be consist with existing naming conventions, | ||
but ultimately comes down to personal preference and indication of | ||
[community consensus](https://github.com/rust-lang/rfcs/pull/2757#issuecomment-544437510) following | ||
the [examples in the rustc codebase](https://github.com/rust-lang/rust/pull/65195). | ||
|
||
- [`to_option` and `to_option_with`](https://github.com/rust-lang/rfcs/pull/2757#issuecomment-529228631) | ||
- [`to_opt` or `then_some`](https://github.com/rust-lang/rfcs/issues/2606#issuecomment-476019577) | ||
- [`then` and `then_do`](https://github.com/rust-lang/rfcs/pull/2180#issuecomment-350498489) | ||
- [`some`](https://github.com/rust-lang/rfcs/issues/2606#issue-387773675) | ||
- [`as_some` and `as_some_from`](https://docs.rs/boolinator/2.4.0/boolinator/trait.Boolinator.html) | ||
- [`some_if` and `lazy_if`](https://github.com/rust-lang/rfcs/pull/2180) | ||
|
||
This functionality could instead be provided by a crate (e.g. | ||
[boolinator](https://docs.rs/boolinator/2.4.0/boolinator/)), but this functionality is commonly | ||
desired and an obvious candidate for the standard library, where an external crate for such simple | ||
functionality is not convenient. | ||
|
||
# Prior art | ||
[prior-art]: #prior-art | ||
|
||
- Jane Street's OCaml Core library contains a | ||
[`some_if`](https://ocaml.janestreet.com/ocaml-core/109.55.00/tmp/core_kernel/Option.html#VALsome_if) | ||
method on `Option`. | ||
|
||
# Unresolved questions | ||
[unresolved-questions]: #unresolved-questions | ||
|
||
None. | ||
|
||
# Future possibilities | ||
[future-possibilities]: #future-possibilities | ||
|
||
Methods for converting from a `bool` to a `Result<T, E>`, e.g. `to_result` and `to_result_with`, | ||
would be obvious candidates for inclusion into the standard library, which could also be included | ||
as an addendum to this proposal if desire is expressed. |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
Might as well mention
if some_condition { t }
as an alternative.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.
Inlining a method body is always a possible alternative, so mentioning it specifically here isn't 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.
@varkor that does not mean inlining the method body, but to make
if x { y }
evaluates toSome(y)
ifx
is true andNone
ifx
is false (basically an even more controversial version of https://internals.rust-lang.org/t/pre-rfc-break-with-value-in-for-while-loops/11208)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.
Ah, I see. Unless there are serious proponents of that approach, I don't think it's worth including, as it seems like an unviable alternative to me.