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

Have a function to convert boolean to Option<()> in std #2227

Closed
ghost opened this issue Nov 25, 2017 · 10 comments
Closed

Have a function to convert boolean to Option<()> in std #2227

ghost opened this issue Nov 25, 2017 · 10 comments
Labels
T-libs-api Relevant to the library API team, which will review and decide on the RFC.

Comments

@ghost
Copy link

ghost commented Nov 25, 2017

Taking inspiration from haskell (http://hackage.haskell.org/package/base-4.10.0.0/docs/Control-Monad.html#v:guard), we could have a guard : fn(bool) -> Option<()> function in std

This lets us write more pleasant code. For example instead of

let x = do catch {
    if is_admin(user) {
        calculate_important_stuff()
    } else {
        None
    }
};

we can do this

let x = do catch {
    guard(is_admin(user))?;
    calculate_important_stuff()
};

basic implementation:

fn guard(b: bool) -> Option<()> {
    if b { Some(()) } else { None }
}

Or maybe even have a Try trait implementation for bool? Not sure if that's beautiful though

@CryZe
Copy link

CryZe commented Nov 25, 2017

I'd prefer having a .to_option method like this:

let x = is_admin(user).to_option(calculate_important_stuff);

@ghost
Copy link
Author

ghost commented Nov 25, 2017

@CryZe, for this case, that indeed looks like a pretty solution. though! it's not as universal as guard, and I wouldn't really expect a function called to_X take any arguments (perhaps map_option or something?)

@fenhl
Copy link

fenhl commented Nov 25, 2017

Why not impl From<bool> for Option<()>?

@fstirlitz
Copy link

Previously in this genre...

@Centril Centril added the T-libs-api Relevant to the library API team, which will review and decide on the RFC. label Dec 6, 2017
@jasonhansel
Copy link

Could bool just be defined as an alias for Option<()>? Correct me if I'm wrong, I think that Option<()> would already be represented as a 0 or 1 in memory, so this wouldn't break C compatibility.

@Centril
Copy link
Contributor

Centril commented Jan 17, 2018

@jasonhansel That would be backwards incompatible. People's crates may assume that bool and Option<()> are different types, so you may have one impl for bool, and one for Option<()>. Making them the same type would create overlapping impls. It might also affect type inference. We could perhaps do this change with a new epoch.

@scottmcm
Copy link
Member

scottmcm commented Feb 24, 2019

I used to think that a Try implementation for bool would be insane, but I'm coming around to it because it would fit really nicely for generalizing the || operator: https://internals.rust-lang.org/t/something-for-coalescing-aka-generalized-improved-or-else/9295/3?u=scottmcm

Edit: And if it did get or_else and and_then and such, then it really might as well support ?.

@jkeiser
Copy link

jkeiser commented Apr 2, 2019

I've seen a few places where this would help reduce cruft like this, where a function checks a condition, and calls a function with an optional error, using a condition to determine if the error is there::

do_thing(index, if array[index] == 0 { Some(UnexpectedZeroError) } else { None });

With this implemented, I could reduce code like this to:

do_thing(index, Option::from(array[index] == 0).map(|| UnexpectedZeroError))

Even better for me, I'd love to see methods like or_some, or_else, and_some, and_else) added to bool:

do_thing(index, (array[index] == 0).or_some(UnexpectedZeroError);

(Even nicer for my case would be (array[index] == 0).or(UnexpectedZeroError), but I'm not sure whether people would be pleasantly or unpleasantly surprised by the fact that (a == 1).or(a == 2) returned Option<bool> and not simply bool.

@burdges
Copy link

burdges commented Apr 3, 2019

Amusingly, this exists as Some(something).filter(|_| is_admin(user)). You'll want the short circuiting version though:

impl bool  { fn map_option<F: FnOnce() -> T>(self, F: F) -> Option<T> {..}  }

If you only have Option<()>: From<bool> then you've short circuiting with is_admin(user).into().map(|()| ..) but not sure if that .into() ever gets ambiguous.

@varkor
Copy link
Member

varkor commented Dec 17, 2019

This is available as condition.then_some(()) now. A method special-cased to () doesn't seem necessary in light of the more general method.

@varkor varkor closed this as completed Dec 17, 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

No branches or pull requests

9 participants