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

Idea: Built-in way to go from bool to Option #2606

Closed
ElectricCoffee opened this issue Dec 5, 2018 · 16 comments
Closed

Idea: Built-in way to go from bool to Option #2606

ElectricCoffee opened this issue Dec 5, 2018 · 16 comments
Labels
T-libs-api Relevant to the library API team, which will review and decide on the RFC.

Comments

@ElectricCoffee
Copy link

ElectricCoffee commented Dec 5, 2018

The idea is pretty simple: Add a function called some to booleans such that you can automatically convert to an option.

The basic implementation wouldn't be much more than

fn some<T>(self, data: T) -> Option<T> {
  if self {
    Some(data)
  } else {
    None
  }
}

The purpose of this would be to be able to write something like regex.is_match(string).some(token) without having to explicitly set up an if-statement.

Maybe also add in an *_or_else style function that takes a closure as an input, such that the true case is only ever allocated if it succeeds: regex.is_match(string).and_some(|| build_token()).

Yes/No/Maybe?
I'd like to hear your opinions :)

@Ixrec
Copy link
Contributor

Ixrec commented Dec 5, 2018

Obligatory link to the boolinator crate (and its silly test comments)

I have no opinion on whether any of this should be uplifted to std

@mark-i-m
Copy link
Member

mark-i-m commented Dec 5, 2018

Personally, I think adding an external crate offsets the convenience of having it. I would rather just have this in std.

@petrochenkov
Copy link
Contributor

cc #2180

@SimonSapin
Copy link
Contributor

SimonSapin commented Dec 5, 2018

I think we should add this, and the closure-based version.

The outcome of #2180 is that we didn’t find consensus on names.

@clarfonthey
Copy link
Contributor

For now, I tend to do Some(data).filter(closure).

@nitnelave
Copy link

This isn't quite equivalent: if the Some is expensive to build, that's where you want the closure. The point of the closure version is that you only need to build the value if you need it.

@zesterer
Copy link

I find myself wanting the ability to "map" a bool with surprising regularity. This feature would be brilliant to see in std.

@frewsxcv frewsxcv added the T-libs-api Relevant to the library API team, which will review and decide on the RFC. label Feb 11, 2019
@canndrew
Copy link
Contributor

Another +1 to this. Should I do a PR for it?

@ElectricCoffee
Copy link
Author

@canndrew please do!

@clarfonthey
Copy link
Contributor

I personally would name this to_some and with_some unless anyone has better suggestions.

@mark-i-m
Copy link
Member

Perhaps to_opt, to_optional, map, with?

@petrochenkov
Copy link
Contributor

petrochenkov commented Mar 25, 2019

Option's map, and and and_then have direct analogues for bool, so it would be reasonable to reuse the names, but the simplest method does not have an analogue.

impl bool {
    fn ???<T>(self, b: T) -> Option<T>; // "closure-less map"
    fn map<T, F>(self, f: F) -> Option<T>  where F: FnOnce() -> T;
    fn and<T>(self, optb: Option<T>) -> Option<T>;
    fn and_then<T, F>(self, f: F) -> Option<T>  where F: FnOnce() -> Option<T>;
}

let my_opt_value = my_bool.???(get_value());
let my_opt_value = my_bool.map(|| get_value());
let my_opt_value = my_bool.and(get_opt_value());
let my_opt_value = my_bool.and_then(|| get_opt_value());

#2180 (comment)

@petrochenkov
Copy link
Contributor

petrochenkov commented Mar 25, 2019

Perhaps Option/Result could have this "closure-less map" as well, it's not a common operation, but search for .map(|_ shows that it's used occasionally.

my_opt.map(|_| ()) // Ignore the data, but keep the "status"

my_opt.map(|_| { // Same as `if my_opt.is_some() { ... }`
    do_things_with_side_effects();
    return_something()
}) 

Or perhaps it's not needed and bool could successfully live with the usual closure-taking map alone.

@ElectricCoffee
Copy link
Author

@petrochenkov the issue with using map is that it already has a very well-defined use in functional programming, namely that it applies a function to a value wrapped in some context. Bool is not a context the way Option or Vec or even HashMap is.

In Haskell terms: map :: (a -> b) -> f a -> f b, which means "given a function from a to b, and a value of type a wrapped in some context f, give me back a value b wrapped in the same context f".

For Option it would look like this: map :: (a -> b) -> Option a -> Option b, which does not fall in line with your suggested map :: (a -> b) -> Bool -> Option b (here reordered to have the function first).

Personally I'd rather go with either @mark-i-m's suggested to_opt or my own some because they don't already clutter the pre-conceived idea of what a "map" should be.

@araspik
Copy link

araspik commented Sep 3, 2019

Any update on the situation? This would be really great to see available in std (instead of having an external dependency), since I often use Meson as a build system on the side (which has huge issues with the Cargo system).

@varkor
Copy link
Member

varkor commented Sep 5, 2019

I've opened an RFC here: #2757.

@Centril Centril closed this as completed Sep 7, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
T-libs-api Relevant to the library API team, which will review and decide on the RFC.
Projects
None yet
Development

Successfully merging a pull request may close this issue.