How do I idiomatically convert a bool to an Option or Result in Rust?
Asked Answered
O

5

53

It seems there is no way of such one-line conversion using std.

I do not like this kind of verbosity:

match my_bool {
    true => Ok(()),
    false => Err(MyError::False),
}

I would like to use a one-liner, for example:

let my_bool = true;
let my_option = my_bool.to_option(MyObject{}); // true => MyObject{}, false => None
let my_result = my_bool.to_result(MyObject{}, MyError{}); // true => MyObject{}, false => MyError{}

What is the shortest piece of code for doing that?

Opsis answered 23/2, 2019 at 12:0 Comment(0)
P
19

This answer is somewhat outdated. Starting with Rust 1.50, you can use the built-in bool::then. See the other answers above for more information.


There is the boolinator crate. It defines the extension trait Boolinator for bool which adds a couple of useful methods. Example:

use boolinator::Boolinator;

my_bool.as_some(MyObject {});                // Option<MyObject>
my_bool.as_result(MyObject {}, MyError {});  // Result<MyObject, MyError>

A true value leads to Some(_) or Ok(_), while a false value leads to None or Err(_).

There is an issue about adding functionality like this to std on the RFCs repository, but it doesn't look like it's happening anytime soon.

Prelature answered 23/2, 2019 at 12:5 Comment(0)
L
65

As of Rust 1.50 you can use bool::then:

assert_eq!(false.then(|| val), None);
assert_eq!(true.then(|| val), Some(val));

You can convert it to a Result by chaining Option::ok_or:

assert_eq!(false.then(|| val).ok_or(err), Err(err));
assert_eq!(true.then(|| val).ok_or(err), Ok(val));

As of Rust 1.62, you can use bool::then_some and pass a value directly instead of creating a closure:

assert_eq!(false.then_some(val), None);
assert_eq!(true.then_some(val), Some(val));

Alternatively, you can use Option::filter:

assert_eq!(Some(obj).filter(|_| false), None);
assert_eq!(Some(obj).filter(|_| true).ok_or(err), Ok(obj));
Lalalalage answered 25/11, 2020 at 21:21 Comment(0)
K
38

bool.then_some() does this:

let my_bool = true;
let my_option = my_bool.then_some(MyObject{});
let my_result = my_bool.then_some(MyObject{}).ok_or(MyError{});

At the time of writing, this is still part of the experimental bool_to_option feature.

Update: As of Rust 1.62, this feature has been stabilized.

Kaylil answered 3/6, 2020 at 6:24 Comment(0)
P
19

This answer is somewhat outdated. Starting with Rust 1.50, you can use the built-in bool::then. See the other answers above for more information.


There is the boolinator crate. It defines the extension trait Boolinator for bool which adds a couple of useful methods. Example:

use boolinator::Boolinator;

my_bool.as_some(MyObject {});                // Option<MyObject>
my_bool.as_result(MyObject {}, MyError {});  // Result<MyObject, MyError>

A true value leads to Some(_) or Ok(_), while a false value leads to None or Err(_).

There is an issue about adding functionality like this to std on the RFCs repository, but it doesn't look like it's happening anytime soon.

Prelature answered 23/2, 2019 at 12:5 Comment(0)
F
8

Use an if expression:

if my_bool { Ok(()) } else { Err(MyError::False) }
Fag answered 25/11, 2020 at 15:29 Comment(0)
M
1

As an alternative to the standard library functions. The then crate provides some and some_with methods on booleans.

use then::Some

// returns Some(value) if my_bool is true
my_bool.some(value); 

// returns Some(value_fn()) if my_bool is true
my_bool.some_with(value_fn); 

Disclaimer: I wrote this crate because I find it annoying that my_bool.some_with(value) is longer than my_bool.some(|| value). And using the _with suffix is more consistent with the Rust naming for lazily evaluated functions.

Monoxide answered 4/3, 2023 at 14:19 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.