Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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?

like image 821
hedgar2017 Avatar asked Feb 23 '19 12:02

hedgar2017


3 Answers

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));
like image 187
Ibraheem Ahmed Avatar answered Nov 08 '22 21:11

Ibraheem Ahmed


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.

like image 28
Michael Koval Avatar answered Nov 08 '22 22:11

Michael Koval


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.

like image 16
Lukas Kalbertodt Avatar answered Nov 08 '22 20:11

Lukas Kalbertodt